[英]Why is `typedef struct x x` allowed?
我正在閱讀《 現代C》這本書,很驚訝地發現以下代碼有效
typedef struct point point;
struct point {
int x;
int y;
};
int main() {
point p = { .x = 1, .y = 2 };
}
但是,這本書沒有詳細介紹。 這是如何運作的? 為什么main()
中的point
引用typedef
因為struct point
是在此之后定義的?
線typedef struct point point;
做兩件事:
struct point
的前向聲明 point
struct point
創建類型別名。 如果您需要在結構完全定義之前就知道其退出,則前向聲明很有用,例如:
typedef struct x X;
typedef struct y {
int a;
X *x;
} Y;
struct x {
int b;
Y *y;
};
在定義struct foo { ... }
之前,可以在許多地方使用struct foo
。 這稱為“不完整類型”。
這很有用,因為它使您可以定義抽象類型:
foo_header.h
struct foo; // abstract
struct foo *foo_create(void);
void do_stuff_with(struct foo *);
void foo_destroy(struct foo *);
這樣,庫的用戶可以使用結構指針和在這些指針上工作的函數,而無需了解結構的實際定義方式,這對於封裝非常有用。
它也用於遞歸類型:
struct node {
int data;
struct node *next; // struct node isn't defined yet!
};
// here the definition of struct node is complete
C支持它,因為它易於實現:要編譯使用struct foo *
代碼,編譯器只需知道指針的大小即可。 它不在乎結構成員。
同樣,在您的typedef
示例中,編譯器不需要知道結構的詳細信息即可為其創建類型別名。
之所以可行,是因為C具有多個名稱空間 :
goto
或尾隨:
); struct
, enum
和union
標記名稱(由struct
, union
或enum
關鍵字消除歧義): struct
和union
成員的名稱(由前導.
或->
消除歧義,每個struct
或union
類型都充當其自己的名稱空間,因此不同的struct
和union
類型可以使用相同的成員名稱); 因此,您可以在同一代碼中使用與標簽相同的名稱,標簽名稱,成員名稱和常規標識符,並且編譯器可以區分它們:
struct x { int x; }; // tag name, member name
void foo( struct x x ) // tag name, all other identifiers
{
if ( x.x ) // all other identifiers, member name
goto x; // label name
// do something here
x: printf( "At label x\n" ); // label name
}
此示例直接來自C標准的6.7.2.3節:
以下替代公式使用typedef機制:
typedef struct tnode TNODE;
struct tnode {
int count;
TNODE *left, *right;
};
TNODE s, *sp;
它向前執行的操作將聲明struct,然后為其創建類型別名。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.