C语言 内存对齐

2022-04-27  本文已影响0人  付凯强

引言

先看一个例子:

typedef struct Test
{
    char a1;
    int a2;
}Test_T;

请问Test_T占几个字节?
如果你的回复是 1 + 4 = 5,那就错了。
我们看下程序运行的结果:

Test_T T;
printf("\nsizeof(T) = %lu\n", sizeof(Test_T));
printf("a1地址:%p\n", &T.a1);
printf("a2地址:%p\n", &T.a2);

sizeof(T) = 8
a1地址:0x7ffd65f12e40
a2地址:0x7ffd65f12e44

程序给出的答案是8个字节。

内存对齐

所谓内存对齐指的是对占用内存较少的类型变量进行内存补齐,对齐占用内存较多的类型变量。在引言中,当char和int放在一起的时候,char自动补齐为4个字节,int占用也是4个字节,加起来就是8个字节。
按照这个理论,那么char和short放在一起,那应该是char自动补齐为2个字节,short两个字节,加起来一共是4个字节。

typedef struct Test
{
    char a1;
    short a2;
}Test_T;
sizeof(T) = 4
a1地址:0x7ffe4138e454
a2地址:0x7ffe4138e456

再看一个例子,把char和long放在一起,那么char自动补齐为8个字节,long是8个字节,加起来是16个字节。

typedef struct Test
{
    char a1;
    long a2;
}Test_T;
sizeof(T) = 16
a1地址:0x7fffb1c08ea0
a2地址:0x7fffb1c08ea8

通过示例证明以上结论是正确的。
以上示例都是两个变量,那再加一个变量呢?

typedef struct Test
{
    char a1;
    int a2;
    char a3;
}Test_T;
sizeof(T) = 12
a1地址:0x7fff4e115adc
a2地址:0x7fff4e115ae0
a3地址:0x7fff4e115ae4

依然证明结论是正确的,编译器为char a3补齐了4个字节的存储空间。
那再加一个char变量呢?

typedef struct Test
{
    char a1;
    int a2;
    char a3;
    char a4;
}Test_T;
sizeof(T) = 12
a1地址:0x7fffa28395ac
a2地址:0x7fffa28395b0
a3地址:0x7fffa28395b4
a4地址:0x7fffa28395b5

你会发现依然是12个字节,按照上面的结论不应该为char a4补齐4个字节的存储空间吗?答案是当a3和a4可以共用4个字节的存储空间的时候,就只会补齐1份4个字节的存储空间。再写一个示例验证下:

typedef struct Test
{
    char a1;
    int a2;
    char a3;
    char a4;
    char a5;
    char a6;
}Test_T;
sizeof(T) = 12
a1地址:0x7ffd38933d9c
a2地址:0x7ffd38933da0
a3地址:0x7ffd38933da4
a4地址:0x7ffd38933da5
a5地址:0x7ffd38933da6
a6地址:0x7ffd38933da7

会发现a3 a4 a5 a6共享一份1个字节的存储空间。

typedef struct Test
{
    char a1;
    int a2;
    char a3;
    char a4;
    char a5;
    char a6;
    char a7;
}Test_T;
sizeof(T) = 16
a1地址:0x7fffe2ebd7f0
a2地址:0x7fffe2ebd7f4
a3地址:0x7fffe2ebd7f8
a4地址:0x7fffe2ebd7f9
a5地址:0x7fffe2ebd7fa
a6地址:0x7fffe2ebd7fb
a7地址:0x7fffe2ebd7fc

会发现单独为char a7补齐了4个字节的存储空间。

总结

typedef struct Test
{
    char a1;
    int a2;
    char a3;
    short a4;
}Test_T;
sizeof(T) = 12
a1地址:0x7fff5d3488fc
a2地址:0x7fff5d348900
a3地址:0x7fff5d348904
a4地址:0x7fff5d348906

编译器会为char a1补齐4个字节的存储空间,会为char a3 、short a4补齐4个字节的存储空间。
所谓补齐,并非是变量真正占用,而是为程序多申请了内存空间。如下图所示


内存对齐.png

可以看到:a1只占用一个字节,为了内存对齐保留了三个空白字节;a3和a4加起来共3字节,为了内存对齐保留了1个空白字节。其实这就是空间换时间的一种思想运用。

参考

https://blog.csdn.net/zhengnianli/article/details/87390212

上一篇下一篇

猜你喜欢

热点阅读