今天在看Linux内核时候,发现了Linux内核的kobject.h文件中,struct kobject 和 struct kset之间貌似有相互包含的关系(这个结论是因为走眼,看掉了一个星号),很是费解,于是就重温了下C语言的结构体引用的相关知识。
在《c程序设计语言(第二版)》中,有类似这样的话:一个包含其自身实例的结构是非法的,但是可以进行自引用,也可以在2个结构体之间进行相互引用。下面解读下这句话:
1. 结构体包含自身实例
一般,用某个数据类型创建变量并赋值,即为实例化。在结构体的定义中,定义一个自身类型的变量,个人认为即是包含自身实例,一个简单的例子:
struct kobject {
char *k_name;
struct kobject kobj;
};
在对包含该结构体定义的文件进行编译时,会出现如下错误: error: field ‘kobj’ has incomplete type
这印证了结构体不能包含自身实例。
2. 结构体的自引用
在C/C 里引用一个数据可以使用指针(*)或引用符号(&),而结构体的自引用结构其实很常见,一个简单的示例:
struct kobject {
char *k_name;
struct kobject *kobj;
};
链表或树等数据结构都包含有这样的自引用结构。
3. 结构体的相互引用
struct kobject {
char *k_name;
struct kset *kset;
};
struct kset {
char *s_name;
struct kobject *kobj;
};
上述示例中,2个结构体kobject和kset定义时分别引用了对方,这是允许的。如果kset定义里面不是引用,而是定义一个kobject实例,这也是允许的(Linux内核里面就是这样做的)。但是,如果这2个结构体里都是定义了对方类型的实例,则会出错,为下面那种情况
4. 结构体相互包含
这种情况下2个结构体定义时相互包含有对方类型的实例,如下:
struct kobject {
char *k_name;
struct kset kset;
};
struct kset {
char *s_name;
struct kobject kobj;
};
这种情况下,文件编译时会报如下错:field ‘kobj’ has incomplete type 。错误类型其实和第一种情况一样。
综上所述:
结构体在使用时,不能包含自身实例,也不能相互包含实例。
联系客服