?
本文檔使用 php中文網(wǎng)手冊 發(fā)布
結構是一種由一系列成員組成的類型,其存儲按有序順序進行分配(與union相反,這是一種由存儲重疊的成員序列組成的類型)。
union
除了使用的關鍵字之外,結構的類型說明符與 類型說明符相同:
結構名稱(可選){結構聲明列表} | (1) | |
---|---|---|
結構名稱 | (2) |
1)結構定義:引入新的類型結構名稱并定義它的含義
2)如果在struct
名稱上使用它自己的行;
,則聲明但不定義該結構name
(請參見下面的前向聲明)。在其他上下文中,命名先前聲明的結構。
name | - | 正在定義的結構的名稱 |
---|---|---|
結構聲明列表 | - | 任何數(shù)量的變量聲明,位域聲明和靜態(tài)斷言聲明。不完整類型的成員和函數(shù)類型的成員是不允許的(除了下面描述的靈活數(shù)組成員) |
在一個結構對象中,其元素的地址(以及位字段分配單元的地址)按照成員定義的順序增加。指向結構的指針可以轉(zhuǎn)換為指向其第一個成員的指針(或者,如果該成員是位域,則指向其分配單元)。同樣,可以將指向結構第一個成員的指針轉(zhuǎn)換為指向封閉結構的指針。在結構的任何兩個成員之間或者在最后一個成員之后,可能存在未命名的填充,但不在第一個成員之前。結構的大小至少與其成員大小的總和一樣大。
如果一個結構至少定義了一個指定的成員,那么它允許額外地聲明它的最后一個成員為不完整的數(shù)組類型。當訪問靈活數(shù)組成員的元素時(在使用運算符的表達式中,或者使用靈活數(shù)組成員的名稱作為右手邊操作數(shù)),那么結構的行為就好像數(shù)組成員具有最長的大小適合為該對象分配的內(nèi)存。如果沒有分配額外的存儲空間,則它的行為就像一個具有1個元素的數(shù)組,除非該行為是未定義的(如果訪問該元素或產(chǎn)生了經(jīng)過該元素的指針)。初始化,sizeof和賦值運算符忽略了靈活的數(shù)組成員。具有靈活數(shù)組成員的結構(或其最后一個成員是具有靈活數(shù)組成員的結構的聯(lián)合結構)不能以數(shù)組元素或其他結構成員的形式出現(xiàn)。struct s {int n; double d []; }; // sd是一個靈活的數(shù)組成員struct s t1 = {0}; // OK,d就好像是double d1,但UB訪問struct s t2 = {1,{4.2}}; //錯誤:初始化忽略靈活數(shù)組//如果sizeof(double)== 8 struct s * s1 = malloc(sizeof(struct s)+ 64); //好像d是雙d8 struct s * s2 = malloc(sizeof(struct s)+ 46); //好像d是double d5 s1 = malloc(sizeof(struct s)+ 10); //現(xiàn)在好像d是double d1 s2 = malloc(sizeof(struct s)+ 6); //相同,但UB訪問double * dp =&(s1-> d0); // OK * dp = 42; // OK dp =&(s2-> d0); // OK * dp = 42; //未定義行為* s1 = * s2; //只復制sn,而不是sd的任何元素//除了在sizeof(struct s)中捕獲的元素外, | (自C99以來) |
---|
類似于聯(lián)合,一個結構的未命名成員的類型是一個沒有名字的結構被稱為匿名結構。匿名結構的每個成員都被認為是封閉結構或聯(lián)合的成員。如果封閉的結構或聯(lián)合也是匿名的,則這將遞歸應用。struct v {union {//匿名聯(lián)合結構{int i,j; }; //匿名結構struct {long k,l; } w; }; int m; } v1; v1.i = 2; //有效v1.k = 3; //無效:內(nèi)部結構不是匿名的v1.wk = 5; // valid與union類似,如果struct沒有任何指定成員(包括通過匿名嵌套結構或聯(lián)合獲得的成員)定義,則程序的行為是未定義的。 | (自C11以來) |
---|
以下表格的聲明。
結構名稱; |
---|
隱藏標簽名稱空間中名稱名稱的任何先前聲明的含義,并將名稱聲明為當前作用域中的新結構名稱,稍后將對其進行定義。在定義出現(xiàn)之前,此結構名稱的類型不完整。
這允許相互引用的結構:
struct y;struct x { struct y *p; /* ... */ };struct y { struct x *q; /* ... */ };
請注意,只需在另一個聲明中使用結構標簽即可引入新的結構名稱,但如果在標簽名稱空間中存在以前聲明的具有相同名稱的結構,則該標簽將引用該名稱。
struct s* p = NULL; // tag naming an unknown struct declares itstruct s { int a; }; // definition for the struct pointed to by pvoid g(void){ struct s; // forward declaration of a new, local struct s // this hides global struct s until the end of this block struct s *p; // pointer to local struct s // without the forward declaration above, // this would point at the file-scope s struct s { char* p; }; // definitions of the local struct s}
struct
.
有關結構初始化程序的規(guī)則,請參閱結構初始化。
因為不完整類型的成員是不允許的,并且結構類型直到定義結束才會完成,所以結構體不能擁有自己類型的成員。允許指向它自己的類型的指針,并且通常用于實現(xiàn)鏈接列表或樹中的節(jié)點。
因為結構聲明不會建立范圍,所以struct-declaration-list中的聲明引入的嵌套類型,枚舉和枚舉器在定義了結構的周圍范圍內(nèi)是可見的。
#include <stddef.h>#include <stdio.h> int main(void){ struct car { char *make; char *model; int year; }; // declares the struct type // declares and initializes an object of a previously-declared struct type struct car c = {.year=1923, .make="Nash", .model="48 Sports Touring Car"}; printf("car: %d %s %s\n", c.year, c.make, c.model); // declares a struct type, an object of that type, and a pointer to it struct spaceship { char *make; char *model; char *year; } ship = {"Incom Corporation", "T-65 X-wing starfighter", "128 ABY"}, *pship = &ship; printf("spaceship: %s %s %s\n", ship.year, ship.make, ship.model); // addresses increase in order of definition // padding may be inserted struct A { char a; double b; char c;}; printf("offset of char a = %zu\noffset of double b = %zu\noffset of char c = %zu\n" "sizeof(struct A)=%zu\n", offsetof(struct A, a), offsetof(struct A, b), offsetof(struct A, c), sizeof(struct A)); struct B { char a; char b; double c;}; printf("offset of char a = %zu\noffset of char b = %zu\noffset of double c = %zu\n" "sizeof(struct B)=%zu\n", offsetof(struct B, a), offsetof(struct B, b), offsetof(struct B, c), sizeof(struct B)); // A pointer to a struct can be cast to a pointer to its first member and vice versa char* pmake = (char*)&ship; pship = (struct spaceship *)pmake;}
可能的輸出:
car: 1923 Nash 48 Sports Touring Car spaceship: 128 ABY Incom Corporation T-65 X-wing starfighter offset of char a = 0offset of double b = 8offset of char c = 16sizeof(struct A)=24offset of char a = 0offset of char b = 1offset of double c = 8sizeof(struct B)=16
C11標準(ISO / IEC 9899:2011):
6.7.2.1結構和聯(lián)合說明符(p:112-117)
C99標準(ISO / IEC 9899:1999):
6.7.2.1結構和聯(lián)合說明符(p:101-104)
C89 / C90標準(ISO / IEC 9899:1990):
3.5.2.1結構和聯(lián)合說明符