memory alignment in C++

96 阅读3分钟

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. 内存对齐对于指导程序员写代码有什么意义?

结构体或者类里面成员的摆放顺序不同,结构体的大小就会不同!!!