结构体的嵌套问题
***************************************************
更多精彩,歡迎進入:http://shop115376623.taobao.com
***************************************************
結構體的自引用(self reference),就是在結構體內部,包含指向自身類型結構體的指針。
結構體的相互引用(mutual reference),就是說在多個結構體中,都包含指向其他結構體的指針。
1. 自引用結構體
1.1 不使用typedef時
錯誤的方式:
struct ?tag_1
{
????struct tag_1 A;??
????int value;
};
????????這種聲明是錯誤的,因為這種聲明實際上是一個無限循環,成員b是一個結構體,b的內部還會有成員是結構體,依次下去,無線循環。在分配內存的時候,由于無限嵌套,也無法確定這個結構體的長度,所以這種方式是非法的。
?
正確的方式:?(使用指針)
struct ?tag_1
{
????struct tag_1 *A;?
????int value;
};
????????由于指針的長度是確定的(在32位機器上指針長度為4),所以編譯器能夠確定該結構體的長度。
1.2 使用typedef 時
錯誤的方式:
typedef struct?
{
????int value;
????NODE *link;?
} NODE;
這里的目的是使用typedef為結構體創建一個別名NODEP。但是這里是錯誤的,因為類型名的作用域是從語句的結尾開始,而在結構體內部是不能使用的,因為還沒定義。
正確的方式:有三種,差別不大,使用哪種都可以。
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;
?
?
2. 相互引用 結構體
錯誤的方式:
typedef ?struct ?tag_a
{
????int value;
????B *bp;?
} A;
typedef ?struct ?tag_b
{
????int value;
????A *ap;
} B;
???????錯誤的原因和上面一樣,這里類型B在定義之前 就被使用。
正確的方式:(使用“不完全聲明”)
struct ?tag_a
{
????struct ?tag_b ?*bp;?
????int value;
};
struct tag_b
{
????struct ?tag_a ?*ap;
????int value;
};
typedef ?struct tag_a ?A;
typedef ?struct tag_b ?B;
struct ?tag_a;??
struct ?tag_b;
typedef ?struct ?tag_a ?A;
typedef ?struct ?tag_b ?B;
struct ?tag_a
{
????struct ?tag_b ?*bp;?
????int ?value;
};
struct ?tag_b
{
????struct ?tag_a ?*ap;
????int ?value;
};
?
?
嵌套結構體時應注意:
結構體的自引用中,如下這種情況是非法的
struct ?s_ref?
{
?int ?a;
?struct s_ref b;
?char c;
};
因為結構體內部又包含自身結構體類型b,這個長度不能確定,只能向下再查找,又包含自身結構體類型b,又再向下查找,如此循環,類似于永無出口的遞歸調用,是非法的。
但很多時候,的確需要使用到自引用,有個技巧,如下:
struct s_ref?
{
?int a;
?struct s_ref *b;??//注意這句與上面相同位置的區別
?char c;
};
這是合法的,因為此處是定義了一個指向結構體的指針,指針的大小在具體的機器平臺和編譯器環境中都是已知的(即使不同的平臺環境的定義不完全相同)。所以不會導致上述的遞歸死循環。是合法和可行的。但是要提醒的是:這個指針看似指向自身,其實不是,而是指向同一類型的不同結構。
鏈表和樹的數據結構就都使用到此技巧。自身的結構體指針指向下一節點或者下一子樹的地址。
這里有一種情況值得注意:
typedef struct {???//這里是結構體類型定義
?int a;
?s_ref *b;??//注意這句引用了結構體類型名
?char c;
}s_ref ;
這個結構體類型定義是為了定義類型名s_ref,但卻失敗了。因為結構體中就引用了結構類型名,而此時還沒定義類型名。
可以改為如下:
typedef struct s_ref_t{???//這里是結構體類型定義和結構體標簽
?int a;
?struct s_ref_t *b;??//注意這句與上面相同位置的區別,使用了標簽
?char c;
}s_ref ;
這里將運行良好。
總結
- 上一篇: latex_列表和表格环境_给tabul
- 下一篇: 关于List转Json的简单方法