來自我的博客minecode.link
在用C來實現數據結構以及部分算法時,經常用到結構體,比如實現樹以及樹的子節點時,就需要該結構體包含自身類型的成員變量。而最近在研究OC的匿名函數實現時,也涉及到了類似需求。同時,兩個結構體之間相互引用也經常遇到問題。故簡單總結一下C語言結構體的自引用語法。
示例
我們以二叉樹的節點為例來看一下自引用:
struct binary_tree {
int data ; // Data area
struct binary_tree * left;
struct binary_tree * right;
};
在樹中,我們需要保存其左右子樹,所以需要引用自身。
結構體自引用
不使用typedef
如果不適用typedef,那么此時我們需要使用struct [名稱]來調用。
但如果按下面的調用方式
struct binary_tree {
int data;
struct binary_tree left;
struct binary_tree right;
};
則會導致在分配內存的時候循環分配,此時編譯器會計算left和right的成員變量并為之分配內存,從而導致嵌套死循環。
struct binary_tree {
int data;
struct binary_tree * left;
struct binary_tree * right;
};
所以后者是正確的,left和right在分配時是以結構體指針的形式來分配內存的。而意義上我們就是為了將其指向另一個binary_tree,所以這樣是復合邏輯的。
使用typedef
使用typedef可以為結構體設置別名,但是要注意的是,typdef的語法為typedef [原類型] [別名];
所以在結構體聲明之前,別名是未定義的。所以我們在內部需要使用其原類型來定義成員變量。
typedef struct binary_tree {
int data;
struct binary_tree * left;
struct binary_tree * right;
}BinTREE;
結構體相互引用
同文件內
使用不完整類型
通過不完整類型語法來實現相互引用
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;
};
不同文件內
對于不同文件,主要有兩點需要注意的。
- 頭文件重復包含問題
- 結構體的聲明問題
而前者通過宏定義解決
#ifndef __FILENAME_H
#define __FILENAME_H
// 代碼
#endif
后者通過上述的“前向聲明”或“不完整類型即可解決”。