结构体内存对齐与类内存对齐

约定不等于承诺〃 2022-03-27 11:00 286阅读 0赞

为什么有内存对齐???

  1. “内存对齐”应该是[编译器][Link 1]的“管辖范围”。编译器为程序中的每个“[数据单元][Link 2]”安排在适当的位置上,便于编译器管理数据。但是C语言的一个特点就是太灵活,太强大,它允许你干预“内存对齐”。如果你想了解更加底层的秘密,“内存对齐”对你就不应该再透明了。对于内存对齐问题,主要存在于structunion等复合结构在内存中的分布情况,许多实际的计算机系统对基本类型数据在内存中存放的位置有限制,它们要求这些数据的首地址的值是某个数M(通常是48);对于“内存对齐”,主要是为了提高程序的性能,数据结构,特别是栈,应尽可能在自然边界上对齐,经过对齐后,cpu的内存访问速度大大提升。

结构体内存对齐规则:

  1. 第一个成员在与结构体偏移量为0的地址处。
  2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
  3. 结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍。
  4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

    注意:对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。VS中默认的对齐数为8,gcc中的对齐数为4

    举个栗子:

    struct A1{

    1. int a;
    2. double b;
    3. char c;
    4. char d;

    };

    struct A2 {

    1. int a;
    2. char c;
    3. char d;
    4. double b;

    };

    struct A3
    {};
    int main()
    {

    1. cout << sizeof(A1) << " " << sizeof(A2) << " " << sizeof(A3) << endl;
    2. system("pause");
    3. return 0;

    }

    结果显示:

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0pvY2hlYmVkNjY2_size_16_color_FFFFFF_t_70

分析:

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0pvY2hlYmVkNjY2_size_16_color_FFFFFF_t_70 1

  1. 为什么空的结构体大小为1???
  2. 你想想,如果我们把struct student 看成一个模子的话,你能造出一个没有任何容积的模子吗?显然不行。编译器也是如此认为。编译器认为任何一种数据类型都有其大小,用它来定义一个变量能够分配确定大小的空间。既然如此,编译器就理所当然的认为任何一个结构体都是有大小的,哪怕这个结构体为空。那万一结构体真的为空,它的大小为什么值比较合适呢?假设结构体内只有一个char 型的数据成员,那其大小为1byte(这里先不考虑内存对齐的情况).也就是说非空结构体类型数据最少需要占一个字节的空间,而空结构体类型数据总不能比最小的非空结构体类型数据所占的空间大吧。这就麻烦了,空结构体的大小既不能为0,也不能大于1,怎么办?定义为0.5byte?但是内存地址的最小单位是1 byte0.5 byte 怎么处理?解决这个问题的最好办法就是折中,编译器理所当然的认为你构造一个结构体数据类型是用来打包一些数据成员的,而最小的数据成员需要1 byte,编译器为每个结构体类型数据至少预留1 byte的空间。所以,空结构体的大小就定位1 byte

类的存储方式:

  1. 与结构体类似,一个类的大小,实际就是该类中”成员变量”之和,当然也要进行内存对齐,注意空类的大小也为1,编译器给了空类一个字节来唯一标识这个类。
  2. 举个栗子:
  3. class A1 {
  4. public:
  5. void f1(){}
  6. private:
  7. int _a;
  8. };
  9. // 类中仅有成员函数
  10. class A2 {
  11. public:
  12. void f2() {}
  13. };
  14. // 类中什么都没有---空类
  15. class A3
  16. {};
  17. int main()
  18. {
  19. cout << sizeof(A1) << " " << sizeof(A2) << " " << sizeof(A3) << endl;
  20. system("pause");
  21. return 0;
  22. }

20190113142318306.png

  1. 即类中关注“成员变量”!!!空类大小为1!!!

发表评论

表情:
评论列表 (有 0 条评论,286人围观)

还没有评论,来说两句吧...

相关阅读

    相关 结构体内对齐

    结构体内存对齐规则 > 1. 第一个成员在与结构体变量偏移量为0的地址处。 > 2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。 > 对齐数 = 编

    相关 c语言结构体内对齐问题

        c语言中结构体使用是非常广泛的,但是结构体有一个问题,就是如果开头的字段属性是字符类型(char),紧跟着的是其他类型,比如整型、长整型、双精度、浮点型,这时候结构体的

    相关 676-为什么要进行结构体内对齐

    为什么要进行结构体内存对齐? 1、平台移植型好 不是所有的硬件平台都能访问任意地址上的数据;某些硬件平台只能只在某些地址访问某些特定类型的数据,否则抛出硬件异常,及遇

    相关 关于结构体内对齐总结

    内存对齐计算可谓是笔试题的必考题,但是如何按照计算原则算出正确答案一开始也不是很容易的事,所以专门通过例子来复习下关于结构体内存对齐的计算问题。(编译环境为vs2015)