一、结构体内存对齐
(1) 如何计算?
首先得掌握结构体的对齐规则;
1、第一个成员在与结构体变量偏移量为0的地址处。
2、其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。 对齐数=编译器默认的一个对齐数与该成员大小的较小值。
**vS中认的对齐数值为8
**Linux环境没有默认对齐数,其自身大小就是默认对齐数。
3.结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。 4、如果嵌套了结构体的情况,(嵌套的结构体对齐至的最大对齐数的整数倍处)结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
(2)计算偏移量
size_t offsetof(structname,membername);
头文件#include<stddef.h>
**所以在我们设计结构体的时候,我们要既满足对齐,又要节省空间,我们应该
让占用空间小的成员尽量集中在一起。
(3)修改默认对齐数
#pragma pack(n)
n就是你要修改的默认对齐数。
二、位段
(1)位段的声明
1、位段的成员必须是int、unsigned、int或者 signed int 及char 。
2、位段的成员名后面有一个冒号和一个数字。
其中位段的空间是按照需要以四字节(int)或者一个字节(char)的方式来开辟的。
还有位段涉及很多不确定性因素,位段是不跨平台的,注重可移植的程序应该避免使用位段。
例如:
它可能是按下图来存放
三、枚举enum
(1)枚举的值
(2)枚举的优点
1、增加代码的可读性和可维护性。
2、和#define定义的标识符比较枚举有类型检查,更加严谨。
3、防止了命名污染(封装)。
4、便于调试。
5、使用方便,一次可以定义多个常量。
四、联合(共用体)
其中c和i共用了一个字节,所以占了4个字节。
但c和i不可以一起使用,因为改变了c值,i的值也会跟着改变。
例如:
用这个来判断编译器的大小端
1、计算联合体大小
1、联合的大小至少是最大成员的大小。
2、当最大成员大小不是最大对齐数的整数倍时,就要对齐到最大对齐数的整数倍。
例如:char数组占五个字节大小,是最大成员,但其对齐数为1,使用要对齐,
所以所占内存为8个字节。
五、柔性数组(结构体中的最后一个元素允许是未知大小的数组,这就叫柔性数组)
(1)特点
1、结构中的柔性数组成员前面必须至少有一个其他成员。
2、sizeof返回的这种结构大小不包括柔性数组的内存。
3、包含柔性数组成员的结构用malloc()函数进行内存的动态分配,并且分配的空间应该大于结构的大小,以适应柔性数组的预期大小。
如下图所示:
(2)优点
1、方便内存释放。
2、可以加快访问速度。