欢迎来到军工软件开发人才培养基地——学到牛牛

内存对齐

时间:2024-05-06 07:01:10 来源:学到牛牛

首先用一段代码演示内存对齐

#include <stdio.h>

 

struct ak{

    short c;

    int b;

    char i;

}a1;

struct bk{

    int b;

    short i;

    char a;

 

}a2;

 

int main()

{

    printf("%d %d \n",sizeof(a1),sizeof(a2));//12  8

    return 0;

}

看到上面的代码大家一定很好奇,为什么相同的元素,只是改变了元素的位置,计算出的结果就完全不相同了,这就是内存对齐导致的。

什么是内存对齐?

在计算机中,内存是按字节划分的,而CPU在读取内存数据时,并不是一字节一字节读取的,实际上是按块来读取的。

块的大小可以是1,2,4,8,16等等,块的大小也称为内存访问粒度。

而内存对齐是将特定的数据类型按照一定的规则摆放在内存上,以此提高CPU访问内存的速度。

为什么要内存对齐?

平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。

性能原因:经过内存对齐后,CPU的内存访问速度大大提升。

在32位设备上,int x,因为CPU对内存的读取操作是对齐的,如果X的地址不是4的倍数,那么读取这个X,需要读取两次共8个字节,然后还要将其拼接成一个int,这比存取内存对齐过的X要麻烦很多。

对齐方式?

每个特定平台上的编译器都有自己默认的“对齐系数”,程序员可以通过预编译命令#pragma pack(n),n=1,2,4,8,16来改变这一系数,其中n就是你要指定的“对齐系数”。

举例验证

同样的我们用上面的程序来验证#pragma pack(n)内存对齐

#include <stdio.h>

#pragma pack(2)

 

struct ak{

    short c;

    int b;

    char i;

 

}a1;

struct bk{

    int b;

    short i;

    char a;

 

}a2;

 

int main()

{

    printf("%d %d \n",sizeof(a1),sizeof(a2));//8 8 

    return 0;

}

当对齐的系数n为2时,只需要结构体成员类型可以整除2,所以打印出的结果都为8。

对齐原则

1.在32位系统中,最大类型长度为成员类型长度最大值和4取较小者。

2.内存对齐后结构体对象内存大小为最大类型长度的倍数

3.结构体对象中成员的起始地址为当前类型长度的倍数