포인터 참조 질문요...

coldman의 이미지

구조체의 필드를 참조할때 우연히 이상한 점이 있네요...

struct temp
{int k ;
};

struct temp * haha = 0;

printf("%d \n", haha->k ) ; //이건 에러가 나는데...
printf("%d \n", &haha->k); // 이건 왜 에러가 안날까요???

어차피 &haha->k 도 haha->k를 참조하고 주소를 얻는거 아닌지요?

죠커의 이미지

아닙니다. haha->k는 (*haha).k의 의미입니다. 즉, haha가 가리키는 곳의 내용 중 k라는 의미 입니다.

->가 1순위 연산자이고 &은 2순위이니 &haha->k의 의미는 &((*haha).k)의 의미가 되는 것입니다. haha가 가리키는 곳의 내용 중 k의 주소를 의미하는 것입니다.

익명 사용자의 이미지

빠른 답변 고맙습니다. :lol:

그런데
&((*haha).k) 를 구하려면
문법적으로 *haha의 값을 읽어와야 하는것 아닐까요??

죠커의 이미지

구조체 멤버의 순서와 메모리 배열의 순서가 동일해야 하기 때문에 멤버 k가 첫번째 멤버니 구조체 자체의 포인터와 같은 위치를 가집니다. haha든 그의 멤버 k이든 동일한 위치를 말합니다. haha가 pointer형이라면 &haha->k의 주소도 못 얻어올 이유는 없을 것입니다.

(표준에서 null인 구조체 pointer의 멤버의 주소를 참조하는데 제약이 있는지는 모르겠습니다. 아마도 undefined이거나 unspecified일 것입니다.)

하지만 null pointer의 값을 참조하는 것은 잘못된 일이기 때문에 에러가 날 것입니다.

doldori의 이미지

엄밀히 얘기하면 undefined이며 따라서 잘못된 코드입니다. 그런데 <stddef.h>에
있는 매크로 offsetof의 정의를 보면 이와 비슷한 코드가 종종 발견됩니다. 예를 들어
MinGW의 gcc 3.4.2를 보면
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
이것은 일종의 hack으로서 특정 구현체의 제작자는 해당 환경에서 이런 코드가
어떤 결과를 보일지 알고 있으므로 이를 구현의 일부로 제공할 수 있습니다.
그러나 어떤 환경에서도 동작하는 코드를 작성해야 하는 사용자의 입장에서는
이런 코드를 쓰면 안됩니다.