memory alignment in C++
1. 为什么要进行内存对齐
现代计算机中内存空间都是按照 byte 划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但是实际的计算机系统对基本类型数据在内存中存放的位置有限制,它们会要求这些数据的首地址的值是某个数k(通常它为4或8)的倍数,这就是所谓的内存对齐。一般地,在32位机器中,32 / 8 = 4 bytes, 所以机器一次访问内存会从中取4个bytes, 对应到C++中有效对齐值就是4。同理,在64位机器中,有效对齐值就是8。
两次访问
一次访问
2. 如何查看电脑的有效对齐值(以linux为例)
只用知道自己的电脑是32位机器还是64位即可
$ uname -a
Linux ... 5.4.0-128-generic #144-Ubuntu SMP Tue Sep 20 11:00:04 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
上图所示为64位机器,在C++中对应的有效对齐值就是8
$ uname -a
Linux pmx0**.**.** 2.6.9-5.ELsmp #1 SMP Wed Jan 5 19:30:39 EST 2005 i686 i686 i386 GNU/Linux
上图所示为32位机器,在C++中对应的有效对齐值就是4
3. 在C++中如何修改有效对齐值
可以通过预编译命令 #pragma pack(n) 进行修改。
不同平台上编译器的 pragma pack 默认值不同。而我们可以通过预编译命令#pragma pack(n), n= 1,2,4,8,16来改变对齐系数。
4. 内存对齐规则
-
结构体第一个成员的偏移量(offset)为0,以后每个成员相对于结构体首地址的 offset 都是该成员大小与有效对齐值中较小那个的整数倍,如有需要编译器会在成员之间加上填充字节。
-
结构体的总大小为 有效对齐值 的整数倍,如有需要编译器会在最末一个成员之后加上填充字节。
5. 举例
x1
struct
{
int i;
char c1;
char c2;
}x1; // 有效对齐值为4: sizeof x1 = 8, 有效对齐值为8: sizeof x1 = 8
struct x1
x2
struct{
char c1;
int i;
char c2;
}x2; // 有效对齐值为4: sizeof x2 = 12, 有效对齐值为8: sizeof x2 = 8
struct x2
x3
struct{
char c1;
char c2;
int i;
}x3; // 有效对齐值为4: sizeof x3 = 8, 有效对齐值为8: sizeof x3 = 8
struct x3
x4
struct{
char c1;
double d;
int i;
}x4; // 有效对齐值为4: sizeof x4 = 16, 有效对齐值为8: sizeof x4 = 24
struct x4
x5
struct{
char c1;
char c2;
double d; // 8
}x5; // 有效对齐值为4: sizeof x5 = 12, 有效对齐值为8: sizeof x5 = 16
struct x5
6. 代码
#include <cstdio>
#include <iostream>
#pragma pack(4) // 记得修改;
using namespace std;
struct
{
int i;
char c1;
char c2;
}x1; // 有效对齐值为4: sizeof x1 = 8, 有效对齐值为8: sizeof x1 = 8
struct{
char c1;
int i;
char c2;
}x2; // 有效对齐值为4: sizeof x2 = 12, 有效对齐值为8: sizeof x2 = 8
struct{
char c1;
char c2;
int i;
}x3; // 有效对齐值为4: sizeof x3 = 8, 有效对齐值为8: sizeof x3 = 8
struct{
char c1;
double d;
int i;
}x4; // 有效对齐值为4: sizeof x4 = 16, 有效对齐值为8: sizeof x4 = 24
struct{
char c1;
char c2;
double d; // 8
}x5; // 有效对齐值为4: sizeof x5 = 12, 有效对齐值为8: sizeof x5 = 16
int main()
{
cout << sizeof(x1) << endl;
cout << sizeof(x2) << endl;
cout << sizeof(x3) << endl;
cout << sizeof(x4) << endl;
cout << sizeof(x5) << endl;
return 0;
}
7. 内存对齐对于指导程序员写代码有什么意义?
结构体或者类里面成员的摆放顺序不同,结构体的大小就会不同!!!