來自我的博客minecode.link
在用C來實現(xiàn)數(shù)據(jù)結(jié)構(gòu)以及部分算法時必怜,經(jīng)常用到結(jié)構(gòu)體,比如實現(xiàn)樹以及樹的子節(jié)點時后频,就需要該結(jié)構(gòu)體包含自身類型的成員變量梳庆。而最近在研究OC的匿名函數(shù)實現(xiàn)時,也涉及到了類似需求卑惜。同時膏执,兩個結(jié)構(gòu)體之間相互引用也經(jīng)常遇到問題。故簡單總結(jié)一下C語言結(jié)構(gòu)體的自引用語法露久。
示例
我們以二叉樹的節(jié)點為例來看一下自引用:
struct binary_tree {
int data ; // Data area
struct binary_tree * left;
struct binary_tree * right;
};
在樹中更米,我們需要保存其左右子樹,所以需要引用自身毫痕。
結(jié)構(gòu)體自引用
不使用typedef
如果不適用typedef征峦,那么此時我們需要使用struct [名稱]來調(diào)用。
但如果按下面的調(diào)用方式
struct binary_tree {
int data;
struct binary_tree left;
struct binary_tree right;
};
則會導(dǎo)致在分配內(nèi)存的時候循環(huán)分配消请,此時編譯器會計算left和right的成員變量并為之分配內(nèi)存栏笆,從而導(dǎo)致嵌套死循環(huán)。
struct binary_tree {
int data;
struct binary_tree * left;
struct binary_tree * right;
};
所以后者是正確的臊泰,left和right在分配時是以結(jié)構(gòu)體指針的形式來分配內(nèi)存的蛉加。而意義上我們就是為了將其指向另一個binary_tree,所以這樣是復(fù)合邏輯的因宇。
使用typedef
使用typedef可以為結(jié)構(gòu)體設(shè)置別名七婴,但是要注意的是,typdef的語法為typedef [原類型] [別名];
所以在結(jié)構(gòu)體聲明之前察滑,別名是未定義的打厘。所以我們在內(nèi)部需要使用其原類型來定義成員變量。
typedef struct binary_tree {
int data;
struct binary_tree * left;
struct binary_tree * right;
}BinTREE;
結(jié)構(gòu)體相互引用
同文件內(nèi)
使用不完整類型
通過不完整類型語法來實現(xiàn)相互引用
struct s_a {
int id;
struct s_b *B_Ptr;
};
struct s_b {
int id;
A *A_Ptr;
};
使用前向聲明
typedef struct s_a A;
typedef struct s_b B;
struct s_a {
int id;
B *B_Ptr;
};
struct s_b {
int id;
A *A_Ptr;
};
不同文件內(nèi)
對于不同文件贺辰,主要有兩點需要注意的户盯。
- 頭文件重復(fù)包含問題
- 結(jié)構(gòu)體的聲明問題
而前者通過宏定義解決
#ifndef __FILENAME_H
#define __FILENAME_H
// 代碼
#endif
后者通過上述的“前向聲明”或“不完整類型即可解決”。