C|不完全类型与结构体的自指向指针

不完全类型指“函数之外、类型的大小不能被确定的类型”。

总结一下,C 的类型分为:

① 对象类型(char、int、数组、指针、结构体等)

② 函数类型

③ 不完全类型:结构体标记的声明、void*。

以上的三种类型都可以派生为指针类型。

对于男性(Man),他可能有妻子(wife)。如果是未婚男性,wife 就是NULL。所以,Man 这样的类型,可以声明成下面这样:

struct Man_tag {
    struct Woman_tag *wife; /*妻*/
};

作为妻子,可以这样声明:

struct Woman_tag {
    struct Man_tag *husband; /*夫*/
};

这种情况下,struct Man_tag 和 struct Woman_tag 是相互引用的,所以无论先声明哪一边都很麻烦。

可以像下面这样通过先声明结构体标记来回避以上问题:

struct Woman_tag; //← 将 tag 提前声明
struct Man_tag {
    struct Woman_tag *wife; /* 妻 */
};
struct Woman_tag {
    struct Man_tag *husband; /* 夫 */
};

在某些环境中,结构体必须使用 typedef,所以,

typedef struct Woman_tag Woman; //← 提前对 tag 进行类型定义
typedef struct {
    Woman *wife; /* 妻 */
} Man;
struct Woman_tag {
    Man *husband; /* 夫 */
};

对这种情况,在 Woman 类型的标记被声明的时候,还不知道其内容,所以无法确定它的大小。这样的类型就称为不完全类型。

因为不能确定大小,所以不能将不完全类型变成数组,也不能将其作为结构体的成员,或者声明为变量。但如果仅仅是用于取得指针,是可以使用不完全类型的。

对于指针声明来说,只要其声明的类型存在(基本类型,或已定义或声明的复合类型),便可以从其派生出指针类型。

上面的结构体 Man,就是将 Woman 类型的指针作为它的成员。之后,在定义 struct Woman_tag 的内容的时候,Woman 就不是不完全类型了。

在 C 标准中,void 类型也被归类为不完全类型。

void*类型表示为类型待定的指针,可以被赋值一个任何类型的地址,只要在指针本身操作或操作指针的指向目标时,类型显式强制转换为原始或期望的类型即可。 指针可以指向为不完全类型,同时,指针不论其目标类型如何,其大小都是固定的一个字长,所以在结构体定义中,可以定义一个自指向的指针,这样的指针并不影响结构体的整体内存分配或布局,所以被定义为链式存储(用来关联数据关系)的语法机制:

struct Node{
    int data;
    struct Node* next; // 指针本身的大小确定(一个字长),与目标类型无关
};

ref

前橋和弥《征服C指针》

-End-

发表评论
留言与评论(共有 0 条评论) “”
   
验证码:

相关文章

推荐文章