结构体的声明与定义
s0,s1,s2都是struct Stu 的别名,即结构体的重命名。(这种情况下就不可以在声明的同时定义变量了)
sp,spp都是sturct Stu类型的
n1为结构体声明的同时定义变量,在下面重新赋值时不能只写n1,还要加上struct Stu。
如果没有对结构体重命名,比如sturct node类型,则在其他作用域中定义变量时,必须加上struct
结构体的自引用
不可以包含struct node n1;只能包含结构体指针。
必须写struct node* 不可写node*
结构体内存对齐
结构体内存对齐是用来计算结构体所占内存的大小的。
首先得掌握结构体的对齐规则:
1. 第一个成员在与结构体变量偏移量为0的地址处。
2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。 对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。 VS中默认的值为8,linux中无默认对齐数,每个成员的对齐数为该成员大小。
3. 结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。
4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
例一:
c1为第一个成员,存放在与结构体变量偏移量为0的地址处。
整型成员i:默认对齐数为8,自身大小为4,取较小值为4,所以存放在偏移量为4的地址处,占用4,5,6,7.之后c2的对齐数为1(1,8取较小值)存放在偏移量为8地址处,此时所有变量存储完毕,根据规则3:结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。所以最大对齐数为4,此时所占内存为9字节,不是4的整数倍,所以向后拓展3个字节。最终占用内存为12个字节。
例2:
同上
例三:
同上
例四:
c1对齐数为1,s3自身大小为16(上一个例子),默认对齐数为8,取8,所以存放在8偏移量的地址处,占16字节,后面再存放d。存放完毕后占32个字节。此时所有成员的最大对齐数为8,(这里并不看s3整体,而是看s3的成员)32为8的整数倍。所以最终占用32个字节。
设计结构体时,让占用空间小的成员尽量集中在一起。可以在满足对齐的基础上节省空间。 (例如例一和例二)
修改默认对齐数
结构体传参
函数传参的时候,参数是需要压栈,会有时间和空间上的系统开销。 如果传递一个结构体对象的时候,结构体过大,参数压栈的的系统开销比较大,所以会导致性能的 下降。
所以:结构体传参的时候,要传结构体的地址。
位段
位段不多应用,大致如上图所示,具有不跨平台性
枚举
枚举:一一列举,类似于#define但是又不同于#define
枚举的使用
联合体(共用体)
a和b公用同一段内存空间,所以称为共用体,可以看到ab的初始地址相同,赋值b为0x55之后,因为char b正好只占1个字节,8bit位,也就是两个16进制位,内存中对应地址处的数据就会被改变。(注:sizeof(u) = 4)
联合体的使用
当给a赋值1时,转化为16进制即0x00000001。如果机器为小端存储,则b所占内存中存储的就是01,如果是大端存储,b所占内存中存储的就是00 以此来判断机器是大端还是小端。