【C语言-进阶】自定义类型详解(结构体+枚举+联合)

结构体的声明与定义

【C语言-进阶】自定义类型详解(结构体+枚举+联合)_第1张图片

s0,s1,s2都是struct Stu 的别名,即结构体的重命名。(这种情况下就不可以在声明的同时定义变量了)

sp,spp都是sturct Stu类型的

n1为结构体声明的同时定义变量,在下面重新赋值时不能只写n1,还要加上struct Stu。

如果没有对结构体重命名,比如sturct node类型,则在其他作用域中定义变量时,必须加上struct

结构体的自引用

【C语言-进阶】自定义类型详解(结构体+枚举+联合)_第2张图片

不可以包含struct node n1;只能包含结构体指针。

必须写struct node* 不可写node*

结构体内存对齐

结构体内存对齐是用来计算结构体所占内存的大小的。

首先得掌握结构体的对齐规则:

1. 第一个成员在与结构体变量偏移量为0的地址处。

2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。 对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。 VS中默认的值为8,linux中无默认对齐数,每个成员的对齐数为该成员大小。

3. 结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。

4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

例一:

【C语言-进阶】自定义类型详解(结构体+枚举+联合)_第3张图片

c1为第一个成员,存放在与结构体变量偏移量为0的地址处。

整型成员i:默认对齐数为8,自身大小为4,取较小值为4,所以存放在偏移量为4的地址处,占用4,5,6,7.之后c2的对齐数为1(1,8取较小值)存放在偏移量为8地址处,此时所有变量存储完毕,根据规则3:结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。所以最大对齐数为4,此时所占内存为9字节,不是4的整数倍,所以向后拓展3个字节。最终占用内存为12个字节。

例2:

【C语言-进阶】自定义类型详解(结构体+枚举+联合)_第4张图片

 同上

例三:

【C语言-进阶】自定义类型详解(结构体+枚举+联合)_第5张图片

 同上

例四: 

【C语言-进阶】自定义类型详解(结构体+枚举+联合)_第6张图片

 c1对齐数为1,s3自身大小为16(上一个例子),默认对齐数为8,取8,所以存放在8偏移量的地址处,占16字节,后面再存放d。存放完毕后占32个字节。此时所有成员的最大对齐数为8,(这里并不看s3整体,而是看s3的成员)32为8的整数倍。所以最终占用32个字节。

设计结构体时,让占用空间小的成员尽量集中在一起。可以在满足对齐的基础上节省空间。 (例如例一和例二)

修改默认对齐数

 【C语言-进阶】自定义类型详解(结构体+枚举+联合)_第7张图片

结构体传参

函数传参的时候,参数是需要压栈,会有时间和空间上的系统开销。 如果传递一个结构体对象的时候,结构体过大,参数压栈的的系统开销比较大,所以会导致性能的 下降。

所以:结构体传参的时候,要传结构体的地址。

位段

【C语言-进阶】自定义类型详解(结构体+枚举+联合)_第8张图片

 位段不多应用,大致如上图所示,具有不跨平台性

枚举

【C语言-进阶】自定义类型详解(结构体+枚举+联合)_第9张图片

枚举:一一列举,类似于#define但是又不同于#define

枚举的使用

【C语言-进阶】自定义类型详解(结构体+枚举+联合)_第10张图片

 【C语言-进阶】自定义类型详解(结构体+枚举+联合)_第11张图片

 联合体(共用体)

【C语言-进阶】自定义类型详解(结构体+枚举+联合)_第12张图片

a和b公用同一段内存空间,所以称为共用体,可以看到ab的初始地址相同,赋值b为0x55之后,因为char b正好只占1个字节,8bit位,也就是两个16进制位,内存中对应地址处的数据就会被改变。(注:sizeof(u) = 4) 

联合体的使用

【C语言-进阶】自定义类型详解(结构体+枚举+联合)_第13张图片 

 当给a赋值1时,转化为16进制即0x00000001。如果机器为小端存储,则b所占内存中存储的就是01,如果是大端存储,b所占内存中存储的就是00 以此来判断机器是大端还是小端。

你可能感兴趣的:(Bit,c语言,开发语言,后端)