• C语言 结构体(联合体)对齐规则


    /* 结构体(联合体)对齐规则 */
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    /*
        * 原则1、第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小的整数倍开始(比如int在32位机为4字节,则要从4的整数倍地址开始存储)。
    
        * 原则2、结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从其内部最宽基本类型大小的整数倍地址开始存储。
    
        *原则3、结构体的总大小为结构体最宽基本类型成员(成员可以是基本类型,也可以是结构体)大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节
    
        *最宽基本类型的概念,所谓基本类型是指像char、short、int、float、double这样的内置数据类型。
    
    */
    
    struct Data1
    {
        int c;   
        char a;  
        char b;  
    };
    
    /*
    struct Data1分析
    分析对齐数
    对齐数的值是 结构体中最宽基本类型成员
    struct Data1最宽类型是int,占4个字节大小,所以对齐数的值是4
    
    根据原则1(第一个数据成员放在offset为0的地方),成员属性c从offset为0的位置开始,成员属性c大小是4个字节,成员属性c从offset为0的位置开始存储,占据4个字节大小
    
    成员属性a从offset为4的位置开始,根据原则1(以后每个数据成员存储的起始位置要从该成员大小的整数倍开始) ,现在offset是4,是1的整数倍
    所以成员属性a从offset为4的位置开始存储,占据1个字节大小
    
    成员属性b从offset为5的位置开始,根据原则1(以后每个数据成员存储的起始位置要从该成员大小的整数倍开始) ,现在offset是5,是1的整数倍
    所以成员属性b从offset为5的位置开始存储,占据1个字节大小
    
    现在struct Data1一共占据6个字节大小的空间,根据原则3(必须是其内部最大成员的整数倍),struct Data1最宽基本类型是int,占4个字节大小
    因此结构体的总大小必须是4的倍数,6不是4的倍数,补齐2个字节,变成8个字节
    结论:struct Data1 大小是8个字节
    
    */
    
    struct Data2
    {
        char a;  
        int c;   
        char b;  
    };
    
    /*
    struct Data2分析
    分析对齐数
    struct Data2最宽类型是int,占4个字节大小,所以对齐数的值是4
    
    根据原则1(第一个数据成员放在offset为0的地方),成员属性a从offset为0的位置开始,成员属性a大小是1个字节,成员属性a从offset为0的位置开始存储,占据1个字节大小
    
    成员属性c是int类型,根据原则1(以后每个数据成员存储的起始位置要从该成员大小的整数倍开始),现在offset是1,1不是4的整数倍
    编译器填充3个字节,现在offset为4 , 4是int的整数倍,成员属性c从offset为4的位置开始存储,占据4个字节大小
    
    成员属性b从offset为8的位置开始,根据原则1(以后每个数据成员存储的起始位置要从该成员大小的整数倍开始) ,现在offset是8,是1的整数倍
    所以成员属性b从offset为8的位置开始存储,占据1个字节大小
    
    现在struct Data2一共占据9个字节大小的空间,根据原则3(必须是其内部最大成员的整数倍),struct Data2最宽基本类型是int,占4个字节大小
    因此结构体的总大小必须是4的倍数,9不是4的倍数,补齐3个字节,变成12个字节
    结论:struct Data1 大小是12个字节
    
    */
    
    struct Data3
    {
        char a;
        short b;
        double c;
    };
    
    /*
    struct Data3分析
    分析对齐数
    struct Data3最宽类型是double,占8个字节大小,所以对齐数的值是8
    
    根据原则1(第一个数据成员放在offset为0的地方),成员属性a从offset为0的位置开始,成员属性a大小是1个字节,成员属性a从offset为0的位置开始存储,占据1个字节大小
    
    成员属性b从offset为1的位置开始,根据原则1(以后每个数据成员存储的起始位置要从该成员大小的整数倍开始) ,现在offset是1,不是short的整数倍
    编译器填充1个字节,现在offset为2 , 2是short的整数倍,成员属性b从offset为2的位置开始存储,占据2个字节大小
    
    成员属性c从offset为4的位置开始,根据原则1(以后每个数据成员存储的起始位置要从该成员大小的整数倍开始) ,现在offset是4,不是double的整数倍
    编译器填充4个字节,现在offset为8 , 8是double的整数倍,成员属性c从offset为8的位置开始存储,占据8个字节大小
    
    现在struct Data3一共占据16个字节大小的空间,根据原则3(必须是其内部最大成员的整数倍),struct Data3最宽基本类型是double,占8个字节大小
    因此结构体的总大小必须是8的倍数,16是8的倍数,不用填充字节
    结论:struct Data3 大小是16个字节
    
    */
    
    struct Data4
    {
        short a;
        char b;
        double c;
        char d[5];
    };
    
    /*
    struct Data4分析
    分析对齐数
    struct Data3最宽类型是double,占8个字节大小,所以对齐数的值是8
    char d[5]并非基本类型
    
    根据原则1(第一个数据成员放在offset为0的地方),成员属性a从offset为0的位置开始,成员属性a大小是2个字节,成员属性a从offset为0的位置开始存储,占据2个字节大小
    
    成员属性b从offset为2的位置开始,根据原则1(以后每个数据成员存储的起始位置要从该成员大小的整数倍开始) ,现在offset是2,是1的整数倍
    成员属性b从offset为2的位置开始存储,占据1个字节大小
    
    成员属性c从offset为3的位置开始,根据原则1(以后每个数据成员存储的起始位置要从该成员大小的整数倍开始) ,现在offset是3,不是double的整数倍
    编译器填充5个字节,现在offset为8 , 8是double的整数倍,成员属性c从offset为8的位置开始存储,占据8个字节大小
    
    成员属性d从offset为16的位置开始,根据原则1(以后每个数据成员存储的起始位置要从该成员大小的整数倍开始) ,现在offset是16,是char的整数倍
    成员属性d从offset为16的位置开始存储,占据1个字节大小
    
    现在struct Data4一共占据17个字节大小的空间,根据原则3(必须是其内部最大成员的整数倍),struct Data3最宽基本类型是double,占8个字节大小
    因此结构体的总大小必须是8的倍数,17不是8的倍数,需要填充7个字节
    结论:struct Data4 大小是24个字节
    
    */
    
    struct Data5
    {
        short a;
        struct Data4 b;
    };
    
    /*
    struct Data5分析
    分析对齐数
    根据原则2, struct Data4最宽类型是double 占8个字节大小,而struct Data5成员a占2个字节,所以对齐数的值是8
    
    根据原则1(第一个数据成员放在offset为0的地方),成员属性a从offset为0的位置开始,成员属性a大小是2个字节,成员属性a从offset为0的位置开始存储,占据2个字节大小
    
    成员属性b从offset为2的位置开始,根据原则2(结构体成员要从其内部最大元素大小的整数倍地址开始存储) ,现在offset是2,不是double的整数倍
    编译器填充6个字节,现在offset为8 , 8是double的整数倍,成员属性b从offset为8的位置开始存储,占据24个字节大小
    
    现在struct Data5一共占据32个字节大小的空间,根据原则3(必须是其内部最大成员的整数倍),struct Data5最宽基本类型是double,占8个字节大小
    因此结构体的总大小必须是8的倍数,32是8的倍数,不需要填充字节
    结论:struct Data5 大小是32个字节
    
    */
    
    struct Data6
    {
        double a;
        struct Data1 b;
    };
    
    /*
    struct Data6分析
    分析对齐数
    根据原则2, struct Data1最宽类型是int 占4个字节大小,而struct Data5成员a 占8个字节,所以对齐数的值是8
    
    根据原则1(第一个数据成员放在offset为0的地方),成员属性a从offset为0的位置开始,成员属性a大小是8个字节,成员属性a从offset为0的位置开始存储,占据8个字节大小
    
    成员属性b从offset为8的位置开始,根据原则2(结构体成员要从其内部最大元素大小的整数倍地址开始存储) ,现在offset是8 ,是 int 的整数倍
    成员属性b从offset为8的位置开始存储,占据8个字节大小
    
    现在struct Data6一共占据16个字节大小的空间,根据原则3(必须是其内部最大成员的整数倍),struct Data6最宽基本类型是double,占8个字节大小
    因此结构体的总大小必须是8的倍数,16是8的倍数,不需要填充字节
    结论:struct Data6 大小是16个字节
    
    */
    
    void test()
    {
        printf("----struct size---1-[%d]------
    ", sizeof(struct Data1));   //8
        printf("----struct size--2--[%d]------
    ", sizeof(struct Data2));   //12
        printf("----struct size--3--[%d]------
    ", sizeof(struct Data3));   //16
        printf("----struct size--4--[%d]------
    ", sizeof(struct Data4));   //24
        printf("----struct size--5--[%d]------
    ", sizeof(struct Data5));   //32
        printf("----struct size--6--[%d]------
    ", sizeof(struct Data6));   //16
    }
    
    int main()
    {
        test();
        printf("-----ok------
    ");
        getchar();
        return 0;
    }
  • 相关阅读:
    BZOJ1819 [JSOI]Word Query电子字典 Trie
    洛谷2973 [USACO10HOL]赶小猪Driving Out the Piggi… 概率 高斯消元
    BZOJ2669 [cqoi2012]局部极小值 状压DP 容斥原理
    BZOJ5047 空间传送装置 2017年9月月赛 最短路 SPFA
    BZOJ5045 打砖块 2017年9月月赛 其他
    BZOJ1858 [Scoi2010]序列操作 线段树
    BZOJ1826 [JSOI2010]缓存交换 堆 贪心
    BZOJ1898 [Zjoi2005]Swamp 沼泽鳄鱼 矩阵
    BZOJ1878 [SDOI2009]HH的项链 树状数组 或 莫队
    BZOJ1875 [SDOI2009]HH去散步 矩阵
  • 原文地址:https://www.cnblogs.com/zhanggaofeng/p/10742113.html
Copyright © 2020-2023  润新知