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

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

上面的代碼可以編譯和Linux下的連接使用GCC。你們中的任何人能向我解釋幕後的事情嗎?我知道這一點需要修復內存大小,所以struct 令牌與sizeof無關,但是即使在gcc中打開警告選項,也沒有關於「none exists」結構的警告。問題的上下文是我正在閱讀其他人的一些源代碼,我非常努力地找到「struct token」的定義,但是當然失敗了。爲什麼它可以使用未定義的結構在C

+6

你不需要'結構令牌'被定義(甚至沒有被聲明)來獲取指向它的指針的大小。 –

回答

12

因爲您正在嘗試獲取指針struct token的大小。指針的大小不取決於實際定義結構的方式。

通常,您甚至可以聲明類型爲struct token*的變量,但不能對其進行取消引用(例如,通過指針訪問成員)。

+0

在C++中,可以聲明'struct token *',但不能聲明'token *'。我不明白爲什麼第二個是不允許的。 – Deqing

+0

因爲只有「標記」不是不完整的類型,而「結構標記」是,所以編譯器無法將「標記」識別爲類型。把它看作只是一個語法限制。 –

9

要解釋C標準,不完整類型是描述對象的類型,但缺少確定其大小所需的信息。

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中通常被稱爲[opaque type](http://en.wikipedia.org/wiki/Opaque_pointer#C),可用於實現面向對象的機制,如封裝和多態。 – Lundin

相關問題