C/C++字节对齐

举报
Linux猿 发表于 2021/08/05 01:34:32 2021/08/05
【摘要】     看到一篇讲解C/C++字节对齐不错的文章:     来源:链接~     字节对齐的原因:         为了提高 CPU 的存储速度,编译器会对 struct 的存储进行优化,即进行字节对齐。 &n...

    看到一篇讲解C/C++字节对齐不错的文章:

    来源:链接~

    字节对齐的原因:

        为了提高 CPU 的存储速度,编译器会对 struct 的存储进行优化,即进行字节对齐。

    对齐方式:

        它们的字节对齐标准就是它的所有成员中字节数最大的数据的字节数。

    一般在32为操作系统的情况下C/C++的变量所占用的字节数:

            char:    1字节;

            short:   2字节;

            int:       4字节;

            long:    4字节;

            long long: 8字节;

            float:    4字节;

            double: 8字节;

            bool:    1字节;

    struct 中字节对齐需要满足的条件:

 

             1、某个变量存放的起始位置相对于结构的起始位置的偏移量是该变量字节数的整数倍;

             2、结构所占用的总字节数是结构种字节数最长的变量的字节数的整数倍。

      例如:


  
  1. struct Struct
  2. {
  3. double d1;
  4. char d2;
  5. int d3;
  6. }a;

用VS查看结果:

上图左边的0,8,12,代表当前变量距离本类初始地址的距离。上图填充值为3

sizeof(a) = 8 + 1 + 3 + 4 = 16。其中补上的 3 个字节是为了让 int 型数据的起始位置相对于结构起始位置的偏移量为 4 的整数倍。


  
  1. struct Struct
  2. {
  3. char d1;
  4. double d2;
  5. int d3;
  6. }b;

VS查看内存输出结果:

 

上图中,填充7是为了分配d2的时候满足前面已经分配的内存大小是d2大小的倍数,最后填充的4个字节是为了满足总的字节数是结构中最大字节数的倍数。

sizeof(b) = 1 + 7 + 8 + 4 + 4= 24。 20 / 8 = 2 …… 4,所以需要再补上 4 个字节,使之成为 8 的 整数倍。

字节对齐的另一种方式:(PS:sizeof 属于关键字)

VC提供了 #pragma pack(n) 用来自定义字节对齐方式,其中n必须是2的幂次方。

    有一下两种情况:

        1、n 大于变量的字节数:偏移量只满足默认的字节对齐方式;

        2、n 小于变量所占的字节数:偏移量默认,总字节长度是n的整数倍。

   例如:


  
  1. #pragma pack(push) // 保持对齐状态
  2. #pragma pack(4) // 设定为 4 字节对齐
  3. struct test
  4. {
  5. double m2;
  6. int m3;
  7. char m1;
  8. };
  9. #pragma pack(pop) // 恢复对齐状态

VS查看类的内存布局:

从上图可以清晰的看到:sizeof(test) = 8 + 4 + 1 + 3 = 16,其中最后的 3 是填充字段。


  
  1. #pragma pack(push) // 保持对齐状态
  2. #pragma pack(16) // 设定为 4 字节对齐
  3. struct test
  4. {
  5. double m2;
  6. int m3;
  7. char m1;
  8. };
  9. #pragma pack(pop) // 恢复对齐状态

VS查看类的内存布局:

大小和上面一样。

再举个栗子:


  
  1. #include <iostream>
  2. using namespace std;
  3. typedef struct A
  4. {
  5. char aChar;
  6. int aInt_2;
  7. short aInt;
  8. }TypeA;
  9. typedef struct B
  10. {
  11. char bChar[3];
  12. TypeA bA;
  13. double bDouble;
  14. }TypeB;
  15. int main()
  16. {
  17. TypeA a;
  18. TypeB b;
  19. cout << sizeof(a) << endl << sizeof(b) << endl;
  20. return 0;
  21. }

类A的内存布局图:

类B的内存布局图:

输出为 12 24

解析:

由上述对字节对齐问题的讨论很容易便可以得出此题的答案。
sizeof(TypeA) = 1 + 3 + 4 + 2 = 10。 10 / 4 = 2 …… 2,故需要再补上 2 个字节,即 sizeof(TypeA) = 12;
sizeof(TypeB) = 3 + 1 + 12 + 8 = 24。之所以补上 1 个字节是因为 TypeA 类型在 struct TypeB 中的默认对齐方式

是 4 个字节(即 int 的字节大小,也即 struct TypeA 中最长的字节)。

看最后一个例子:


  
  1. typedef struct A
  2. {
  3. char aChar;
  4. int aInt_2;
  5. short aInt;
  6. }TypeA;
  7. typedef struct B
  8. {
  9. TypeA bA;
  10. double bDouble;
  11. }TypeB;

类B的内存布局:

可进一步看一下C++中计算类的大小:C++类的大小计算

文章来源: blog.csdn.net,作者:Linux猿,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/nyist_zxp/article/details/80201210

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。