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

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

上記のコードは、Linuxでgccを使用してコンパイルおよびリンクすることができます。あなたの誰かが私のためにシーンの背後にあることを説明できますか?私はポイントがメモリの固定サイズを取ることを知っているので、struct トークンはsizeofとは関係ありませんが、gccの警告オプションをオンにしても、 "none exist"構造体に関する警告はありません。質問のコンテキストは、他の人がソースコードを読んでいることです。構造体トークンの定義を見つけるのが非常に難しいですが、コースが失敗しました。なぜcでundefined structを使用できるのですか

+6

あなたは '構造体のトークンを必要としません'それを指すポインタにサイズを渡すために定義される(宣言されることさえありません)。 –

答えて

12

ポインタstruct tokenのサイズを取得しようとしているためです。ポインタのサイズは、構造が実際にどのように定義されているかに依存しません。

一般に、タイプstruct token*の変数を宣言することもできますが、逆参照することはできません(たとえば、ポインタでメンバーにアクセスするなど)。

+0

C++では 'struct token *'を宣言できますが、 'token *'は宣言できません。なぜ私は2番目のものが許可されていないのか分かりません。 – Deqing

+0

"トークン"は不完全な型ではないので、 "struct token"はコンパイラが型として "token"を認識できないためです。それを単なる構文上の制限と考えてください。 –

9

C標準の言い換えでは、不完全型は オブジェクトを記述する型ですが、サイズを決定するために必要な情報はありません。

voidは、もう1つの不完全な型です。他の不完全な型とは異なり、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

関連する問題