jun-wiki

View My GitHub Profile

Posts (Latest 10 updated) :
Read all
Contents:
  1. 포인터
  2. 포인터 산술
  3. 배열과 포인터
  4. 미니 치트시트

오늘 간단한 퀴즈 봤는데

개같이 봐가지고 관련해서 공부하려 한다

쥐뿔도 몰라도 정글 올 수 있다고 홍보하지만

진짜 쥐뿔도 모르면 주옥같은 일이 벌어질테니 어느정도 알고가자


별건 아니고 C에서의 포인터 연산자와 배열간의 관계다

알면 쉽지만 모르면 맞아야 한다 ㅇㅇ

검색하면 더 잘나올테지만 그래도 대강 설명해보겠다



포인터

*, &이 대표적으로 존재한다

&x를 가정한다면 이는 x의 위치(메모리 주소)를 의미한다 -> 참조

*p를 가정한다면 p의 값을 의미한다 -> 역참조

예시

int x = 10;      // 값
int *p = &x;     // p는 x의 주소를 담음
*p = 20;         // 역참조로 x를 바꿈 -> x == 20

관련해서 void**도 있다

void의 경우 어떤 타입이든 가리킬 수 있다

타입같은 건 신경 안쓰고 그냥 가리키는 터라 역참조는 불가능하다. C에서는 값바꾸거나 하려면 타입을 알아야 메모리 위치에 기록가능하니 말이다

**는 이중 포인터라고 하는데 별 거 아니고 **p라고 한다면 *p를 가리키는 거다
실제 값이 *p를 통해 알 수 있다면 *p의 위치를 **p로 알아서 *p를 갖고 놀 수 있는거다

const란 것도 있는데 읽기 전용으로 만드는 거다

아무튼 위의 내용은 당연한 내용이다

좀 어려운 건 포인터 산술이다

이는 배열과도 연관이 있는 상당히 중요한 내용이다



포인터 산술

p + n, p - n, p++, p-- : 타입 크기 단위로 이동

int *p; p+1은 다음 int로 이동

여기서 왜 void는 역참조 불가한지 알 수 있다

포인터 산술에서 이동할때 int라는 타입을 알기에 int 타입의 바이트만큼 메모리 주소에서 이동하는데
void의 경우 타입이 전무하기에 몇바이트 이동해야하는지 프로그램에서 알지 못한다

void를 역참조 하고 싶을시 올바른 타입으로 캐스팅 꼭 해줘야 한다

void *vp = malloc(sizeof(int));
*(int*)vp = 7;    // 캐스트 후 역참조
free(vp);

그리고 포인터 산술을 할때에는 순서가 중요하다

C 주의점에서 관련된건 확인해봐라 (사실 보지 마라 여기가 더 꼼꼼하다)

대충 이런거다

int a[]={1,2,3};
int *p = a;
printf("%d\n", *p++); // 1 출력, p는 이제 a+1
printf("%d\n", (*p)++); // 2 출력하고, 그 칸 값이 3이 됨
printf("%d\n", *++p); // p를 먼저 a+2로, 그 값 3 출력
  • *p++ == *(p++)
  • (*p)++는 역참조한 값 증가

여러 산술식을 쓸 때 괄호를 잘 씌워주라 이 말이야



배열과 포인터

배열은 사실상 포인터라고 한다

파이썬과 좀 달라서 개념이 헷갈렸다

C에서 2차원 배열은 1차원 메모리의 연속이다
예: int a[R][C];

a[0][0] a[0][1] ... a[0][C-1] | a[1][0] ... a[1][C-1] | ... | a[R-1][0] ... a[R-1][C-1]
^ a (== &a[0])                  ^ a+1 (== &a[1])        ...   ^ a+(R-1) (행 포인터 관점)


주소 공식(중요):

int a[R][C];
&a[i][j] == (int*)a + (i*C + j) == *(a + i) + j        // 타입: int*
a[i][j] == * ((int*)a + i*C + j)  == *(*(a + i) + j)   // 타입: int



그리고 크기 구할때에도 차이가 있다

int a[10];
int *p = a;          // int*
int (*pa)[10] = &a;  // int (*)[10]
printf("%zu %zu\n", sizeof a, sizeof p);   // 40(예: 4바이트 int) vs 8(포인터)

별건 아니고 배열 크기냐 포인터 크기냐다



미니 치트시트

// 선언 읽기
int *p;           // p: pointer to int
int **pp;         // pp: pointer to pointer to int
int (*fp)(void);  // fp: pointer to function(void) returning int
int (*ap)[10];    // ap: pointer to array[10] of int

// const 위치
const int *p;     // pointer to const int
int * const p2 = &x;         // const pointer to int
const int * const p3 = &x;   // const pointer to const int

// 산술/우선순위
*p++   // *(p++)  : 현재값 사용 후 p 이동
(*p)++ // 그 칸의 값 증가
*++p   // p 먼저 이동 후 역참조
*(p+1) // 다음 요소

// 배열/포인터 차이
sizeof a     // 배열 크기 전체
sizeof &a    // 배열 포인터 크기
sizeof p     // 포인터 크기


좀 대충 다뤘기에 다음에 몇번 추가로 다루겠다
(아마도)