簡體   English   中英

為什么允許`typedef struct xx`?

[英]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或尾隨: );
  • structenumunion標記名稱(由structunionenum關鍵字消除歧義):
  • structunion成員的名稱(由前導.->消除歧義,每個structunion類型都充當其自己的名稱空間,因此不同的structunion類型可以使用相同的成員名稱);
  • 所有其他標識符(變量和函數名稱,typedef名稱,枚舉常量等)。

因此,您可以在同一代碼中使用與標簽相同的名稱,標簽名稱,成員名稱和常規標識符,並且編譯器可以區分它們:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM