===============================================================================
结构体的自引用(c++)
结构体作为一种类型,起成员可以是各种基本类型,当然也包括结构体这种类型。当一个结构体中想引用自身的结构时,是可以的,不过要注意用法。下面第一种是错误的,即我刚开始想象的那样子。第二种是正确的。 1.结构体定义中错误的自身引用: struct A { int a; int b; A c; }pp;
为什么错误呢,这个大家应该可以想象,第三个成员c是个A类型,c的第三个成员也是个A类型,那么会一直有pp.c.c.c.c.c.c.c……,此结构体的大小没有结束,那么肯定是错误的,编译的时候肯定通不过。那么怎么能是引用自身呢,这就要看指针的功能了。 2.结构体定义中错误的自身引用: struct A { int a; int b; A *c; }pp;
这样使用指针指向一个自身的结构体,那么第三个元素是个指针,占用一个地址空间的大小,那么pp的大小就是一个int,一个int,再一个指针的大小。c的具体内容需要在实际用的时候去赋值。这样就达到了自身引用的效果。而操作系统中使用的链表的实现也就是这样来的: Structlist_head {
Structlist_head *next, *prev;
};
structdevice{ ……
Structlist_head list; …… }
假设在32位机器上,list_head的大小占用8字节,共存储两个指针,分别指向他的前一个节点和后一个节点。
指针变量占用内存的大小(字节数).在32位机上,所有指针类型变量占用内存字节数都为4因为32位机就是 4字节 * 8个二进制位/字节计算出来的.如果在64位机上,指针占用内存大小就是:8个字节.
===============================================================================
C语言中结构体 自引用 和 相互引用(c++)
结构体的自引用(self reference),就是在结构体内部,包含指向自身类型结构体的指针。 结构体的相互引用(mutual reference),就是说在多个结构体中,都包含指向其他结构体的指针。
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时
错误的方式: typedefstruct { int value;
NODE *link; /* 虽然也使用指针,但这里的问题是:NODE尚未被定义 */ } NODE;
这里的目的是使用typedef为结构体创建一个别名NODEP。但是这里是错误的,因为类型名的作用域是从语句的结尾开始,而在结构体内部是不能使用的,因为还没定义。 正确的方式:有三种,差别不大,使用哪种都可以。 /* 方法一 */ typedefstructtag_1{ intvalue;
struct tag_1 *link; } NODE; /* 方法二 */ structtag_2;
typedefstructtag_2 NODE; struct tag_2{ int value;
NODE *link; };
2. 相互引用结构体
错误的方式:
typedefstructtag_a{ int value;
B *bp; /* 类型B还没有被定义 */ } A;
typedefstructtag_b{ int value; A *ap; } B;
错误的原因和上面一样,这里类型B在定义之前就被使用。
正确的方式:(使用“不完全声明”) /* 方法一 */ Structtag_a{
structtag_b *bp; /* 这里structtag_b还没有定义,但编译器可以接受 */ int value; };
Structtag_b{ structtag_a *ap; intvalue; };
Typedefstructtag_a A; Typedefstructtag_bB; /* 方法二 */
Structtag_a; /* 使用结构体的不完整声明(incomplete declaration) */ Structtag_b;
typedefstructtag_aA; typedefstructtag_bB; structtag_a{
structtag_b*bp; /* 这里structtag_b还没有定义,但编译器可以接受 */ intvalue; };
Structtag_b{ Structtag_a*ap; intvalue; };