C++语言结构体和指针指针也可以指向一个结构体,定义的形式一般为:struct结构体名*变量名;下面是一个定义结构体指针的实例:上述代码已经测试。
注意:定义已经命名的结构体指针的时候必须用已命名结构体类型定义的结构体变量的地址进行初始化。
也可以在定义结构体的同时定义结构体指针:上述代码已经测试注意,结构体变量名和数组名不同,数组名在表达式中会被转换为数组指针,而结构体变量名不会,无论在任何表达式中它表示的都是整个集合本身,要想取得结构体变量的地址,必pstu赋值只能写作:struct stu *pstu = &stu1;而不能写作:struct stu *pstu = stu1;还应该注意,结构体和结构体变量是两个不同的概念:结构体是一种数据类型,是一种创建变量的模板,编译器不会为它分配内存空间,就像int、float、char 这些关键字本身不占用内存一样;结构体变量才包含实实在在的数据,才需要内存来存储。
下面的写法是错误的,不可能去取一个结构体名的地址,也不能将它赋值给其他变量:struct stu *pstu = &stu;struct stu *pstu = stu;获取结构体成员通过结构体指针可以获取结构体成员,一般形式为:(*pointer).memberName或者:pointer->memberName对了。
,有了它,可以通过结构体指针直接取得结构体成员;这C语言中的唯一用途。
上面的两种写法是等效的,我们通常采用后面的写法,这样更加直观。
运行结果:Name Num Age Group ScoreZhou ping 5 18 C 145.0Zhang ping 4 19 A 130.5Liu fang 1 18 A 148.5Cheng ling 2 17 F 139.0Wang ming 3 17 B 144.5结构体指针作为函数参数结构体变量名代表的是整个集合本身,作为函数参数时传递的整个集合,也就是所有成员,而不是像数组一样被编译器转换成一个指针。
如果结构体成员较多,尤其是成员为数组时,传送的时间和空间开销会很大,影响程序的运行效率。
所以最好的办法就是使用结构体指针,这时由实参传向形参的只是一个地址,非常快速。
要铭记的一点就是:数组名称始终代表数组的指针指向第一个元素,数组名称加一始终指向下一个数组元素。
c语言函数说明必须在主调函数之前,就是在开头先声明这个函数,告诉系统有这个函数,或者你要调用的函数放在前面。
然后你再调用。
只能对结构体变量中的成员赋值,而不能对结构体类型赋值对结构体变量中的成员(即“域”),可以单独使用,它的作用与地位相当于同类型的普通变量结构体的成员也可以是一个结构体变量===============================================================================结构变量的三种定义方式以上只是指定了一种结构体类型,它相当于一个模型,但其中并无具体数据,系统也不为之分配实际的内存单元为了能在程序中使用结构体类型的数据,应当定义结构体类型的变量,并在其中存放具体的数据。
定义结构体类型变量的方法可以采取以下3种方法定义结构体类型的变量。
1) 先声明结构体类型再定义变量名如上面已定义了一个结构体类型Student,可以用它来定义结构体变量。
如:在C语言中,在定义结构体变量时,要在结构体类型名前面加上关键字Sttuct,C++ 保留了C的用法,如:struct Student studentl, student2;提倡读者在编写C++程序时,使用C++新提出来的方法,即不必在定义结构体变量时加关键字Struct,这样使用更方便,而且与第8章中介绍的用类(class)名定义类对象的用法一致。
以上定义了student1和student2为结构体类型Student的变量,即它们具有Student类型的结构。
如图7.2所示。
图7.2在定义了结构体变量后,系统会为之分配内存单元。
例如student1和student2在内存中各占63个字节(4+20+1+4+4+30=63)。
2) 在声明类型的同时定义变量。
例如:这种形式的定义的一般形式为:struct结构体名{成员表列}变量名表列;3) 直接定义结构体类型变量。
其一般形式为:struct //注意没有结构体类型名{成员表列}变量名表列;这种方法虽然合法,但很少使用。
关于结构体类型,有几点要说明:1) 不要误认为凡是结构体类型都有相同的结构。
实际上,每一种结构体类型都有自己的结构,可以定义出许多种具体的结构体类型。
2) 类型与变量是不同的概念,不要混淆。
只能对结构体变量中的成员赋值,而不能对结构体类型赋值。
在编译时,是不会为类型分配空间的,只为变量分配空间。
3) 对结构体中的成员(即“域”),可以单独使用,它的作用与地位相当于普通变量。
4) 成员也可以是一个结构体变量。
=============================================================================== 结构体的自引用(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;};。