对于结构体来经常会涉及到内存对齐问题,如下面代码所示:
#include <stdio.h>
struct Test
{
short x1;
char x2;
float x3;
char x4;
};
int main(void)
{
struct Test t;
//printf("0x%p\n", &t.x1);
//printf("0x%p\n", &t.x2);
//printf("0x%p\n", &t.x3);
//printf("0x%p\n", &t.x4);
printf("sizeof(char) = %lu", sizeof(char));
printf("sizeof(char) = %lu", sizeof(int));
printf("sizeof(char) = %lu", sizeof(short));
printf("%lu\n", sizeof(t));
return 0;
}
执行该段代码可以得到以下结果:
我是在VS2015下进行的编译,可以得到各自变量所占的长度以及结构体所占长度,一般按照字面来说,结构体所占字节数应该为:
2+1+4+1 = 8,但是事实上该结构体最终的长度为12,此时就涉及到内存对齐的问题;
2、内存对齐规则
不同的平台的特定编译器都有自己默认的“对齐系数”。我们可以强制指定对齐系数,通过#pragma pack(k), k = 1,2,4,8,16等;
也可以通过#pragme pack()取消已经指定的对齐系数,对齐的规则如下:
规则一:
struct或者union中,起始的offset为0,对齐系数为#pragma pack指定的和自身所占字节数中较小的那个值进行对齐,如下代码所示:
#pragma pack(4)
struct Test
{
short x1;
char x2;
float x3;
char x4;
};
现在已经占了9字节的长度,但是实际上所占长度为12,这为什么呢?我们看内存对齐规则二。
规则二:
在struct或者union元素对齐后,struct或者union整体也要进行对齐操作,对齐将按照,#pragma pack和struct或者union中成员中最大数据成员中较小的那个进行;
则对于以上的例子来说,pragma pack为4,结构体中最大数据成员长度也为4,则结构提整体以4位对齐系数进行对齐,已经有9个字节,则补3字节为12字节。所以整个结构体长度为12。
3、其他对场景举例
* 场景一:
#pragma pack(1)
struct Test
{
short x1;
char x2;
float x3;
char x4;
};
整体struct对齐系数为:pragma pack(1) 和 float中较小者为 1;
则整体结构体所占长度为8.
*场景二:
#pragma pack(8)
struct Test
{
short x1;
char x2;
float x3;
char x4;
};
现在所占字节为:9
整体struct对齐系数为:pragma pack(8) 和 float中较小者为 4;
则整体结构体所占长度为12。
4、结尾
内存对齐对于c/c++程序员来说是必须要掌握的一个点,也是各种面试和笔试中常考的点,至此将内存对齐做了一个总结,以备后续查阅。