轉載網址:http://tscsh.blog.163.com/blog/static/20032010320138249183520/數據結構
今天關於結構體一些疑問,在這裏標記一下spa
結構體的定義以下所示,struct爲結構體關鍵字,tag爲結構體的標誌,member-list爲結構體成員列表,其必須列出其全部成員;variable-list爲此結構體聲明的變量。指針
1 struct tag 2 { 3 member-list 4 } variable-list ;
在通常狀況下,tag、member-list、variable-list這3部分至少要出現2個。如下爲示例:code
1 //此聲明聲明瞭擁有3個成員的結構體,分別爲整型的a,字符型的b和雙精度的c 2 //同時又聲明告終構體變量s1 3 //這個結構體並無標明其標籤 4 struct { 5 int a; 6 char b; 7 double c; 8 } s1; 9 10 11 //此聲明聲明瞭擁有3個成員的結構體,分別爲整型的a,字符型的b和雙精度的c 12 //結構體的標籤被命名爲SIMPLE,沒有聲明變量 13 struct SIMPLE{ 14 int a; 15 char b; 16 double c; 17 }; 18 //用SIMPLE標籤的結構體,另外聲明瞭變量t一、t二、t3 19 struct SIMPLE t1, t2[20], *t3; 20 //也能夠用typedef建立新類型 21 typedef struct{ 22 int a; 23 char b; 24 double c; 25 } Simple2; 26 //如今能夠用Simple2做爲類型聲明新的結構體變量 27 Simple2 u1, u2[20], *u3;
在上面的聲明中,第一個和第二聲明被編譯器看成兩個徹底不一樣的類型,即便他們的成員列表是同樣的,若是令t3=&s1,則是非法的。結構體的成員能夠包含其餘結構體,也能夠包含指向本身結構體類型的指針,而一般這種指針的應用是爲了實現一些更高級的數據結構如鏈表和樹等。blog
若是兩個結構體互相包含,則須要對其中一個結構體進行不完整聲明,以下所示:內存
//結構體A中包含指向結構體B的指針 struct A { struct B *partner; //other members; }; //結構體B中包含指向結構體A的指針,在A聲明完後,B也隨之進行聲明 struct B { struct A *partner; //other members; };
1.1 不使用typedef時作用域
錯誤的方式:編譯器
1 struct tag_1 2 { 3 struct tag_1 A; /* 結構體 */ 4 int value; 5 };
這種聲明是錯誤的,由於這種聲明其實是一個無限循環,成員b是一個結構體,b的內部還會有成員是結構體,依次下去,無線循環。在分配內存的時候,因爲無限嵌套,也沒法肯定這個結構體的長度,因此這種方式是非法的。io
正確的方式: (使用指針):編譯
1 struct tag_1 2 { 3 struct tag_1 *A; /* 指針 */ 4 int value; 5 };
因爲指針的長度是肯定的(在32位機器上指針長度爲4),因此編譯器可以肯定該結構體的長度。
1.2 使用typedef 時
錯誤的方式:
1 typedef struct 2 { 3 int value; 4 NODE *link; /* 雖然也使用指針,但這裏的問題是:NODE還沒有被定義 */ 5 } NODE;
這裏的目的是使用typedef爲結構體建立一個別名NODEP。可是這裏是錯誤的,由於類型名的做用域是從語句的結尾開始,而在結構體內部是不能使用的,由於還沒定義。
正確的方式:有三種,差異不大,使用哪一種均可以。
1 /* 方法一 */ 2 typedef struct tag_1{ 3 int value; 4 struct tag_1 *link; 5 } NODE; 6 7 8 /* 方法二 */ 9 struct tag_2; 10 typedef struct tag_2 NODE; 11 struct tag_2{ 12 int value; 13 NODE *link; 14 }; 15 16 17 /* 方法三 */ 18 struct tag_3{ 19 int value; 20 struct tag_3 *link; 21 }; 22 typedef struct tag_3 NODE;
錯誤的方式:
1 typedef struct tag_a{ 2 int value; 3 B *bp; /* 類型B尚未被定義 */ 4 } A; 5 6 typedef struct tag_b{ 7 int value; 8 A *ap; 9 } B;
錯誤的緣由和上面同樣,這裏類型B在定義之 前 就被使用。
正確的方式:(使用「不徹底聲明」)
1 /* 方法一 */ 2 struct tag_a{ 3 struct tag_b *bp; /* 這裏struct tag_b 尚未定義,但編譯器能夠接受 */ 4 int value; 5 }; 6 struct tag_b{ 7 struct tag_a *ap; 8 int value; 9 }; 10 typedef struct tag_a A; 11 typedef struct tag_b B; 12 13 14 /* 方法二 */ 15 struct tag_a; /* 使用結構體的不完整聲明(incomplete declaration) */ 16 struct tag_b; 17 typedef struct tag_a A; 18 typedef struct tag_b B; 19 struct tag_a{ 20 struct tag_b *bp; /* 這裏struct tag_b 尚未定義,但編譯器能夠接受 */ 21 int value; 22 }; 23 struct tag_b{ 24 struct tag_a *ap; 25 int value; 26 };