2012-05-25 3 views
11
#include <stdio.h> 

int main() 
{ 
    printf("%d", sizeof(struct token *)); 
} 

위의 코드는 Linux에서 gcc로 컴파일하고 링크 할 수 있습니다. 여러분 중 누군가가 나에게 장면 뒤에있는 것을 설명 할 수 있습니까? 나는 포인트가 메모리의 픽스 크기를 차지한다는 것을 알고 있으므로 struct 토큰은 sizeof와는 관련이 없지만 gcc의 경고 옵션을 켜기조차도 "존재하지 않는"구조체에 대한 경고는 표시하지 않습니다. 질문의 문맥은 다른 사람들이 소스 코드를 읽는 것입니다. "struct token"에 대한 정의를 찾기가 매우 어려워요. 물론 그 과정은 실패했습니다.왜 c에서 undefined struct를 사용할 수 있습니까?

+6

필요하지 않은'구조체 토큰 '를 정의하고 (선언하지 않아도) 포인터를 가리키는 크기를 얻는다. –

답변

12

포인터의 크기를 얻기 위해에서 struct token까지 포인터를 가져 오려고합니다. 포인터의 크기는 구조체가 실제로 어떻게 정의되는지에 달려 있지 않습니다.

일반적으로 struct token* 유형의 변수를 선언 할 수도 있지만 역 참조 할 수는 없습니다 (예 : 포인터를 통해 구성원에 액세스).

+0

C++에서는'struct token *'을 선언 할 수 있지만'token *'을 선언 할 수는 없습니다. 나는 왜 두 번째 것이 허용되지 않는지 이해하지 못한다. – Deqing

+0

"token"은 불완전한 형식이 아니기 때문에 "struct token"은 컴파일러가 "token"을 유형으로 인식 할 수 없기 때문에. 그것을 구문 론적 한계라고 생각하십시오. –

9

불완전한 유형은 객체를 설명하지만 크기를 결정하는 데 필요한 정보가 부족한 유형입니다.

void는 또 다른 불완전한 유형입니다. 다른 불완전 유형과 달리 void는 을 완료 할 수 없습니다.

이 "불완전 유형"은 핸들 종류에 자주 사용됩니다. 라이브러리는 "핸들"을 무언가에 할당하고 함께 처리 한 다음 다시 처리 할 수있게합니다. 이 모든 일은 라이브러리에 캡슐화됩니다. 사용자는 내부에서 어떤 일이 일어날 지 모릅니다.

예 :

lib.h :

struct data * d_generate(void); 
void d_set(struct data *, int); 
int d_get(struct data *); 
void d_free(struct data*); 

lib.c :

#include "lib.h" 
#include <stdlib.h> 
struct data { int value; }; 
struct data * d_generate(void) { 
    return malloc(sizeof(struct data)) 
} 
void d_set(struct data * d, int v) { 
    d -> value = v; 
} 
int d_get(struct data * d) { 
    return d->value; 
} 
void d_free(struct data* d) { 
    free(d); 
} 

user.c :

#include "lib.h" 
[...] 
struct data * d = d_generate(); 
d_set(d, 42); 
int v = d_get(d); 
// but v = d->value; doesn't work here because of the incomplete definition. 
d_free(d); 
+1

이것은 C의 [불투명 한 유형] (http://en.wikipedia.org/wiki/Opaque_pointer#C)으로 일반적으로 알려져 있으며 캡슐화 및 다형성과 같은 객체 지향 메커니즘을 달성하는 데 사용할 수 있습니다. – Lundin

관련 문제