结构体的内存对齐规则、位段的内存分配、枚举的优点
结构体
如何对齐
1. 将结构体第一个成员放在与结构体偏移量为0的地址处;
2. 其他成员要对齐到对齐数的整数倍处,对齐数 = 编译器默认的一个数字 与 该成员大小的较小值。
3. 结构体的总大小为对最大齐数的整数倍。对齐原因
1. 栈上存储的数据内存尽可能的在自然边界上对齐。
2. 为了访问未对齐的内存,处理器需要做两次访问,而访问对其的内存只需要访问一次。
3. 这是一种以空间换时间的做法。为了节省空间,我们可以把内存空间占用小的成员定义在一起。结构体传参
1. 在结构体传参时:struct S s = {1,2,3};
…test(&s)
√test(s)
×
2. 我们应该传地址,不能传结构体,因为函数传参时,参数是要压栈的,如果传结构体,压栈开销比较大,会影响性能。
位段的内存分配
位段(位域)是一个或多个位的字段,不同长度的字段存储在一个或多个其所声明类型的变量中。
例如:
struct st1 { unsigned char a:7; /*字段a占用了一个字节的7个bit*/ unsigned char b:2; /*字段b占用了2个bit*/ unsigned char c:7; /*字段c占用了7个bit*/ }s1; sizeof(s1)等于3。 struct st2 { unsigned int a:31; unsigned int b:2;/*前一个整型变量只剩下1个bit,容不下2个bit,所以只能存放在下一个整型变量*/ unsigned int c:31; }s2; sizeof(s2) = 3*sizeof(int) = 12
一个字节8个bit位,根据声明类型的大小,来判断结构体位域的大小
我们可以使用#define,为什么要用枚举?
枚举的优点
1. 增加了代码的可读性与可维护性,
2. 跟#define相比,枚举具有类型检查,更加安全严谨
3. 便于调试
4. 使用方便,一次可以定义多个常量
5. 将其封装起来可以防止命名污染