淘先锋技术网

首页 1 2 3 4 5 6 7

内存对齐

现代计算机体系中CPU按照双字、字、字节访问存储内存,字是计算机进行数据处理和运算的单位,若未经一定规则的对齐,CPU的访址操作将会异常的复杂,所以现代编译器中都会对内存进行自动对齐。

数据成员对齐

结构体 struct 中的成员在内存中的分配是连续的,struct 内的首地址就是 struct 内第一个数据成员的地址,即 struct 内第一个数据成员离 struct 开始的距离 offset = 0。

对齐规则:

  • 结构体第一个成员的偏移量(offset)为0,以后每个成员相对于结构体首地址的 offset 都是该成员大小与有效对齐值中较小那个的整数倍,如有需要编译器会在成员之间加上填充字节;
  • 结构体的总大小为 有效对齐值 的整数倍,如有需要编译器会在最末一个成员之后加上填充字节;
  • 结构体内类型相同的连续元素将在连续的空间内,和数组一样。

https://songlee24.github.io/2014/09/20/memory-alignment/

类型长度

sizeof的基本作用是判断数据类型或者表达式的长度(字节数)。
(注意:sizeof不是一个函数,而是一个C++中的关键字)

64位Visual Studio 2017环境下,C++内置类型长度:

cout << sizeof(char) << endl;  // 1
cout << sizeof(short) << endl;  // 2
cout << sizeof(int) << endl;  // 4
cout << sizeof(long) << endl;  // 4
cout << sizeof(long long) << endl;  // 8
cout << sizeof(double) << endl;  // 8

规则总结

连续申明的变量是否可以在内存中连续存储(即不填充字节),由变量长度之和是否超出一个块(有效对齐值个字节构成一个块,例如,8个字节为1个块)决定。

例如(8字节对齐):

struct
{
	int a;  // 4
	char b;  // 1
	double c;  // 8
}// 16

int a 占4字节,char b占1字节,加起来为5个字节,不超过1个块,可以连续存储。double c 占8个字节,加起来13个字节,超过1个块,double c 在下一个块中存储。所以,最后存储情况为:4字节 int a,1字节 char b,3字节填充,8字节 double c,共16字节。

struct
{
	char a;
	double c;
}st;

cout << sizeof(st) << endl;  // 16

内存对齐系数

#pragma pack的主要作用就是改变编译器的内存对齐方式,#pragma pack(n) 的作用是改变编译器的对齐系数,n 值可取(1,2,4,8,16),默认8字节对齐。


参考:https://www.jianshu.com/p/49ddb946a226