1.定義與聲明
結構體的定義如下所示,struct為結構體關鍵字,tag為結構體的標誌,member-list為結構體成員列表,其必須列出其所有成員;variable-list為此結構體聲明的變數。
[cpp] view plaincopyprint?
- struct tag { member-list } variable-list ;
在一般情況下,tag、member-list、variable-list這3部分至少要出現2個。以下為樣本:
[cpp] view plaincopyprint?
- //此聲明聲明了擁有3個成員的結構體,分別為整型的a,字元型的b和雙精確度的c
- //同時又聲明了結構體變數s1
- //這個結構體並沒有標明其標籤
- struct {
- int a;
- char b;
- double c;
- } s1;
- //此聲明聲明了擁有3個成員的結構體,分別為整型的a,字元型的b和雙精確度的c
- //結構體的標籤被命名為SIMPLE,沒有聲明變數
- struct SIMPLE{
- int a;
- char b;
- double c;
- };
- //用SIMPLE標籤的結構體,另外聲明了變數t1、t2、t3
- struct SIMPLE t1, t2[20], *t3;
- //也可以用typedef建立新類型
- typedef struct{
- int a;
- char b;
- double c;
- } Simple2;
- //現在可以用Simple2作為型別宣告新的結構體變數
- Simple2 u1, u2[20], *u3;
在上面的聲明中,第一個和第二聲明被編譯器當作兩個完全不同的類型,即使他們的成員列表是一樣的,如果令t3=&s1,則是非法的。結構體的成員可以包含其他結構體,也可以包含指向自己結構體類型的指標,而通常這種指標的應用是為了實現一些更進階的資料結構如鏈表和樹等。
如果兩個結構體互相包含,則需要對其中一個結構體進行不完整聲明,如下所示:
[cpp] view plaincopyprint?
- struct B; //對結構體B進行不完整聲明
- //結構體A中包含指向結構體B的指標
- struct A {
- struct B *partner;
- //other members;
- };
- //結構體B中包含指向結構體A的指標,在A聲明完後,B也隨之進行聲明
- struct B{
- struct A *partner;
- //other members;
- };
2. 自引用 結構體
1.1 不使用typedef時
錯誤的方式:
[cpp]
view plaincopyprint?
- struct tag_1{
- struct tag_1 A; /* 結構體 */
- int value;
- };
這種聲明是錯誤的,因為這種聲明實際上是一個無限迴圈,成員b是一個結構體,b的內部還會有成員是結構體,依次下去,無線迴圈。在分配記憶體的時候,由於無限嵌套,也無法確定這個結構體的長度,所以這種方式是非法的。
正確的方式: (使用指標):
[cpp]
view plaincopyprint?
- struct tag_1{
- struct tag_1 *A; /* 指標 */
- int value;
- };
由於指標的長度是確定的(在32位機器上指標長度為4),所以編譯器能夠確定該結構體的長度。
1.2 使用typedef 時
錯誤的方式:
[cpp]
view plaincopyprint?
- typedef struct {
- int value;
- NODE *link; /* 雖然也使用指標,但這裡的問題是:NODE尚未被定義 */
- } NODE;
這裡的目的是使用typedef為結構體建立一個別名NODEP。但是這裡是錯誤的,因為類型名的範圍是從語句的結尾開始,而在結構體內部是不能使用的,因為還沒定義。
正確的方式:有三種,差別不大,使用哪種都可以。
[cpp]
view plaincopyprint?
- /* 方法一 */
- typedef struct tag_1{
- int value;
- struct tag_1 *link;
- } NODE;
-
-
- /* 方法二 */
- struct tag_2;
- typedef struct tag_2 NODE;
- struct tag_2{
- int value;
- NODE *link;
- };
-
-
- /* 方法三 */
- struct tag_3{
- int value;
- struct tag_3 *link;
- };
- typedef struct tag_3 NODE;
3. 相互引用 結構體
錯誤的方式:
[cpp]
view plaincopyprint?
- typedef struct tag_a{
- int value;
- B *bp; /* 類型B還沒有被定義 */
- } A;
-
- typedef struct tag_b{
- int value;
- A *ap;
- } B;
錯誤的原因和上面一樣,這裡類型B在定義之 前 就被使用。
正確的方式:(使用“不完全聲明”)
[cpp]
view plaincopyprint?
- /* 方法一 */
- struct tag_a{
- struct tag_b *bp; /* 這裡struct tag_b 還沒有定義,但編譯器可以接受 */
- int value;
- };
- struct tag_b{
- struct tag_a *ap;
- int value;
- };
- typedef struct tag_a A;
- typedef struct tag_b B;
-
-
- /* 方法二 */
- struct tag_a; /* 使用結構體的不完整聲明(incomplete declaration) */
- struct tag_b;
- typedef struct tag_a A;
- typedef struct tag_b B;
- struct tag_a{
- struct tag_b *bp; /* 這裡struct tag_b 還沒有定義,但編譯器可以接受 */
- int value;
- };
- struct tag_b{
- struct tag_a *ap;
- int value;
- };