C中的字节对齐¶
对齐跟数据在内存中的位置有关。
字长¶
在16位的CPU中,一个字刚好为两个字节;在32位CPU中,一个字是四个字节。若以字为单位,还有双字,四字
我们先来看看下面这个例子:
上面这个例子中各个变量所占的字节分别是多少呢?我们逐个分析一下:
struct Node{
int a; // 0~3 int(4 byte)
char b; // 4~5 char(1 byte)
double c; // 6~13 double(8 byte)
};
所以答案就是:0~13一共14个字节
真的是这样吗?
答案是:肯定不是啊!
在计算机中,内存的存储和读取都是16的整数倍个字节,这是由CPU cache Line 决定的,一般是64个字节连续从读取(在Linux 32bit 操作系统情况下),所以不可能是14个字节存储的。
这就引出了本次要讲的东西:叫做字节对齐。
字节对齐¶
字节对齐有以下原则:
-
变量的字节大小计算是从0开始的
-
变量所占的内存空间是变量所占字节大小的整数倍,比如
int
是4个字节,则所占内存就是8、12等4的倍数 -
变量所占空间位置要是变量的整数倍,比如
int
是4个字节,所以有关于int
的变量要从4的整数倍开始计算内存空间 -
字节对齐有个概念叫做对齐模数,可以说是用来对齐内存的标准。
- 对于结构体而言,在对齐完各个变量之后,要再对整体进行以此拓展,让整个结构体内存对齐:
具体做法是:将整个结构体当中所占字节最大的变量与对齐模数进行比较,取小的数;
让整个结构体拓展到最接近结构体字节数的上述取小值的倍数。
例如:一个结构体在初次对齐完之后是20个字节,对齐模数是8,所以应该将结构体的内存拓展到最接近20的8的倍数值,即24。
了解了字节对齐原则,返回看上面的例子,正确的解法应该是:
// pragma pack(n)
struct Node{
int a; // 0~3
char b; // 4~7
double c; // 8~15
};
/* 初次对齐为 0~15 ,所以是16个字节
* 结构体中所占字节最大的变量类型为 double: 8
* 对齐模数默认值为: 8
* 取小值:(这里是一样大小)8
* 16是8的整数倍,所以不用继续做拓展
*/
再来看看结构体嵌套结构体的情况:
对于结构体嵌套结构体的情况,其实就是将结构体变量在所嵌套的结构体中展开,然后用相同的方法解决:
具体解析如下: