• 内存对齐规则


    前言

            求结构体的大小是很热门的考点,无论你是学C还是C++,都会遇到这样的问题,在面试中也很受欢迎,所以我们先思考这样一个问题:计算结构体,联合体和类的大小应该怎么去计算呢?我们知道,在C语言中结构体内部可以包含很多变量,所以我们在没有学习这个知识之前,会固化地认为,结构体的大小就是内部变量的大小的总和,但是事实就是这样吗?显然并不是,那接下来我们就要去学习一下如何求结构体它们的大小

    一、内存对齐规则(每一个都是重点

    1. 第一个成员永远在与结构体变量偏移量为0的地址处。

    2. 其他成员变量要对齐到 自身对齐数的整数倍 的地址处。

    对齐数 = 编译器默认的一个对齐数该成员大小较小值

    只有VS中默认对齐数值为8
    其他编辑器(gcc,clang)的对齐数就是成员自身的大小

    3. 结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍

    4. 如果一个结构体的成员有另一个结构体类型的变量,这个结构体类型的变量要对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数的整数倍。

    5. 当结构体里有数组的时候,我们数组的对齐数是数组中一个元素的大小,之后在占整个数组大小的空间。

    5. 使用下面的代码可以设置默认对齐数:

    1. #include
    2. #pragma pack(8)//设置默认对齐数为8
    3. struct S1
    4. {
    5. char c1;
    6. int i;
    7. char c2;
    8. };
    9. #pragma pack()//取消设置的默认对齐数,还原为默认

    二、求结构体大小的例题 (都按编辑器没有默认对齐数)

    1. 例题1

    1. #include
    2. struct S1
    3. {
    4. char c1;
    5. int i;
    6. char c2;
    7. };
    8. int main()
    9. {
    10. printf("%lu",sizeof(struct S1));
    11. return 0;
    12. }

    答案及解析 12

    2. 例题2

    1. #include
    2. struct S2
    3. {
    4. char c1;
    5. char c2;
    6. int i;
    7. };
    8. int main()
    9. {
    10. printf("%lu\n", sizeof(struct S2));
    11. return 0;
    12. }

    答案及解析 8

    153. 例题3

    1. #include
    2. struct S3
    3. {
    4. double d;
    5. char c;
    6. int i;
    7. };
    8. int main()
    9. {
    10. printf("%lu\n", sizeof(struct S3));
    11. return 0;
    12. }

    答案及解析 16

    4. 例题4 (嵌套结构体)

    1. #include
    2. struct S3
    3. {
    4. double d;
    5. char c;
    6. int i;
    7. };
    8. struct S4
    9. {
    10. char c1;
    11. struct S3 s3;
    12. double d;
    13. };
    14. int main()
    15. {
    16. printf("%lu\n", sizeof(struct S4));
    17. return 0;
    18. }

    答案及解析 32

    5. 例题5(结构体内部有数组)

    1. #include
    2. struct S1
    3. {
    4. char c1;
    5. int arr[6];
    6. };
    7. int main()
    8. {
    9. printf("%lu",sizeof(struct S1));
    10. return 0;
    11. }

    答案及解析 28

    三、联合体的计算规则

    联合体是共用同一块空间的;

    1. 联合的大小至少是最大成员的大小

    2. 当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍

    3. 数组的对齐数是数组的一个元素的大小,再占整个数组大小的空间。

    四、求union联合体大小的例题

    1. 例题1

    1. #include
    2. union Un1
    3. {
    4. char c[5];
    5. int i;
    6. };
    7. int main()
    8. {
    9. printf("%lu\n", sizeof(union Un1));
    10. return 0;
    11. }

    答案及解析  8

    2. 例题2

    1. #include
    2. union Un2
    3. {
    4. short c[7];
    5. int i;
    6. };
    7. int main()
    8. {
    9. printf("%lu\n", sizeof(union Un2));
    10. return 0;
    11. }

    答案及解析 16

    五、求类大小

    向结构体看齐,一样的规则哦!但是有几点不跟结构体一样;

    1. 类的内部有成员变量和成员函数,我们只算成员变量的就行,不需要算成员函数;

    2. 不包含成员变量的类默认的大小是1字节,空类也是1字节

    3. 静态成员变量不属于实例化对象,所以不会占类的空间,因为静态成员变量是一种特殊的静态全局变量,写在类里是为了表明它在哪个作用域而已。

    4. 类里面包含类,计算大小的时候,不需要算类里面的类,内部的类其是跟我们外部的类平行的关系,放在类里面只是为了在访问的时候,需要指明在哪个作用域里。

    1. 例题1

    1. #include
    2. using namespace std;
    3. class A
    4. {
    5. public:
    6. void Print()
    7. {
    8. cout << "Print()" << endl;
    9. }
    10. private:
    11. };
    12. int main()
    13. {
    14. cout << sizeof(A) << endl;
    15. return 0;
    16. }

    答案及解析 1

    没有成员变量的类大小为1个字节;

    2. 例题2

    1. #include
    2. using namespace std;
    3. class A
    4. {
    5. public:
    6. void Print()
    7. {
    8. cout << "Print()" << endl;
    9. }
    10. private:
    11. double _a;
    12. char _b;
    13. int _c;
    14. };
    15. int main()
    16. {
    17. cout << sizeof(A) << endl;
    18. return 0;
    19. }

    答案及解析 16

    算类的大小,只需要算成员变量的大小,不需要算成员函数,因为成员函数属于类的共有部分,每个实例化对象都有这个函数,难道我们每次实例化一次对象,就要创造成员函数吗?很显然不是,因为太消耗空间里,而每个实例化对象都必须有属于自己的成员变量,这是毋庸置疑的;

    3. 例题3 (静态成员变量)

    1. #include
    2. using namespace std;
    3. class A
    4. {
    5. public:
    6. void Print()
    7. {
    8. cout << "Print()" << endl;
    9. }
    10. private:
    11. double _a;
    12. static int _b;
    13. };
    14. int main()
    15. {
    16. cout << sizeof(A) << endl;
    17. return 0;
    18. }

    答案及解析 8

    静态成员变量是所有类的实例化对象共享的,并不是每个对象都要创建的,所以跟成员函数一个道理,不用算

    4. 例题4 (类类型的成员变量)

    1. #include
    2. using namespace std;
    3. class A
    4. {
    5. public:
    6. void Print()
    7. {
    8. cout << "Print()" << endl;
    9. }
    10. private:
    11. double _a;
    12. };
    13. class B
    14. {
    15. private:
    16. int _b;
    17. A _a;
    18. };
    19. int main()
    20. {
    21. cout << sizeof(B) << endl;
    22. return 0;
    23. }

    答案及解析 16

    要注意的是这不是内部类,是在成员变量里有一个A类类型的变量,这就跟结构体里面有另外一个结构体变量一样,如果一个结构体的成员有另一个结构体类型的变量,这个结构体类型的变量要对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数的整数倍。

    5. 例题5 (内部类)

    1. #include
    2. using namespace std;
    3. class A
    4. {
    5. public:
    6. void Print()
    7. {
    8. cout << "Print()" << endl;
    9. }
    10. private:
    11. double _a;
    12. class B
    13. {
    14. private:
    15. int _b;
    16. };
    17. };

    答案及解析 8​​​​​​​

    内部类不需要算,因为是与外部类平行的关系

  • 相关阅读:
    逐鹿千亿市场:一碗中国面的魅力
    [答疑]校长出轨主任流程的业务建模
    RabbitMQ 学习(一)-- 概念和安装
    write tcp 127.0.0.1:53226->127.0.0.1:6379: use of closed network connection
    Java读和写文件
    深度学习入门:针对deep-learning-for-image-process文件的学习
    大数据计算,如何优化SQL?
    Mybatis - Spring整合后一级缓存失效了
    Hutool工具说明和使用步骤
    基础不牢的把vue的插槽再好好看下吧
  • 原文地址:https://blog.csdn.net/2302_76941579/article/details/134330130