关于内存对齐

关于内存对齐

要理解内存对齐,首先明白一个概念,在现代计算机体系中,CPU从内存中拿数据,CPU与内存通过总线连接,进行数据读写。在x86体系下,总线位宽是32位,这也是所有指针类型都占用4个字节的原因。既然总线位宽是32位,那就意味着CPU一次可以从内存拿到连续4个字节的数据。这样,将数据按照相隔4字节进行存放,存取的效率是最高的,相邻距离在4字节以内,存取效率反而会降低了。64位系统与之同理,只不过64位系统一次可读写的值是8字节。

为了提高存取的效率,编译器在存放结构体的时候,会默认对结构体的成员进行内存对齐,也就是在结构体的各个成员后面填充空字节,使填充后的结构体大小满足对齐要求,从面更方便CPU读写,对齐的规则如下:

  1. 只按char、short、int、float、double、指针等“原子类型”对齐,结构体嵌套时,需要将子结构体展开成原子类型。
  2. char对齐值为1,short对齐值为2,int、float对齐值为4字节,指针和double的对齐值和体系结构有关,32位系统下,指针和double的对齐值为4字节,64位系统下则为8字节。注意在32位系统下,double类型的大小为8字节,但对齐值为4字节。
  3. 32位系统下的系统对齐值为4字节,64位系统下的系统对齐值为8字节。
  4. 成员变量相对于结构体起始位置的偏移,必须是该成员对齐值与系统对齐值这两者较小值的整数倍
  5. 整个结构体的大小,必须是结构体对齐值的整数倍。结构体对齐值为系统对齐值与结构体成员中的最大对齐值这两者的较小值

例如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
using namespace std;
struct st1
{
char a ;
int b ;
short c ;
};

struct st2
{
short c ;
char a ;
int b ;
};

int main()
{
cout<<"sizeof(st1) is "<<sizeof(st1)<<endl; //sizeof(st1) is 12
cout<<"sizeof(st2) is "<<sizeof(st2)<<endl; //sizeof(st2) is 8
return 0 ;
}

评论