美文网首页
C语言 内存对齐

C语言 内存对齐

作者: 付凯强 | 来源:发表于2022-04-27 12:49 被阅读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

    相关文章

      网友评论

          本文标题:C语言 内存对齐

          本文链接:https://www.haomeiwen.com/subject/bovkyrtx.html