C语言的sizeof运算符计算结构体大小

C语言的sizeof运算符计算结构体大小,第1张

C语言的sizeof运算符运算规则 sizeof运算符
**sizeof 是一个运算符,不是函数(方法)。

** 例子: 当想打印一个变量的存储区域大小时,可以直接写 int a = 5; printf("%d\n",sizeof a); 当想打印一个数据类型的存储区域大小时,因为int是数据类型,所以要加小括号提高int的运算优先级 printf("%d\n",sizeof(int));

C中不同数据类型所占用的内存大小

对于32位系统来说,大小如下(单位:字节)

sizeof计算结构体大小
  • 结构体的成员可以是不同的数据类型,成员被声明后顺序存放在一块连续的内存区域。

  • 结构体的大小不是简单的相加,需要考虑系统在存储结构体时的数据对齐。

  • 需要引入一个概念:偏移量。

偏移量指的是结构体变量中成员的地址和结构体变量地址的差

  • 结构体首个数据的偏移量为0。

  • 结构体后一个成员的偏移量 = 前一个成员的偏移量+补充字节+成员大小
  • 结构体大小等于最后一个成员大小加上偏移量
    例子:
    struct aa
    {
        int a;
        char c;
        int b;
    };
    
 	printf("%d\n",sizeof(struct aa));

答案是:12

偏移量补充字节成员大小
004
401
534

偏移量5+3=8 结构体大小8+4=12
在实际中,存储变量时地址要求对齐,编译器在编译程序时会遵循两条原则:
(1)结构体变量中成员的偏移量必须是成员数据类型大小的整数倍(0被认为是任何数的整数倍)
(2)结构体大小必须是所有成员大小的整数倍,也即所有成员大小的公倍数。


第一个成员a的偏移量是0,第二个成员c的偏移量是0+0+4=4,因为成员大小是1,所以不需要补充字节。

第三个成员b的偏移量是4+0+1=5,因为成员大小是4,遵循原则(1),需要3个补充字节,偏移量就是5+3=8,结构体大小即8+4=12。

12遵循了原则(2),所以正确。

sizeof计算结构体中存放数组

举例:

    struct aa
    {
        int a;
        char c[6];
        int b;
    };
    
 	printf("%d\n",sizeof(struct aa));

答案是16。

第二个成员c的偏移量是0+0+4=4,不需要补充字节,因为4是char的整数倍;成员b的大小是4,所以需要连个补充字节,偏移量即是10+2=12,得出结构体大小是12+4=16

sizeof计算结构体中存放结构体

嵌套结构体存放,需要展开计算
(1)第二个成员的偏移量为展开的成员中,最大的成员(数据类型占字节最大)的整数倍。


(2)结构体的大小,是展开后所有成员的整数倍
注意:必须展开,嵌入的结构体不能当成一个整体成员计算。


举例:

    struct aa
    {
        int a;
        char c[3];
        struct bb
        {
            int e[5];
            double f[2];
        };
        
        int b;
    };
    
 	printf("%d\n",sizeof(struct aa));//打印答案是:56
  1. 可以看到结构体中int e[5]的成员最大,因为要展开,所以是成员f最大,不是e(可以回看上面存放数组sizeof理解)
  2. 因为展开后f最大,所以结构体aa.c的偏移量是8(对照原则(1))
  3. 因为结构体大小是所有成员的整数倍,所以结构体aa的大小是56,否则是52。

    (对照原则(2))

偏移量补充字节成员大小
004
443
12020
32016
4804

48+0+4=52,结构体大小必须是展开后所有成员大小的整数倍(数据对齐),所以52+4=56。

sizeof计算结构体中存放联合体(共用体)union

什么是联合体?

  1. 联合体也叫共用体,在C语言中定义联合体的关键字是union
  2. 联合体的所有成员在内存中具有相同的首地址,共占同一段内存空间,这些成员可以相互覆盖,因此联合体也常常被称作共用体,在不同的时间保存不同的数据类型和不同长度的成员的值。

    也就是说,在某一时刻,只有最新存储的成员是有效的。

    运用此种类型数据的优点是节省存储空间。


    所以计算结构体中嵌套的共用体时,不管最新存储了哪个成员,占用的内存空间不会超过共用体里面定义的最大成员占用的最大空间。

sizeof计算结构体中存放联合体(共用体)union的计算原则,和sizeof计算结构体中存放结构体一样,都需要展开,并对照那两条原则去计算。

区别就是共用体的成员大小只需要计算最大的。


举例:

    struct aa
    {
        int m1;
        char m2;
        float m3;
        union uu{
            char u1[5];
            int u2[2];
        }ua;
    }myaa;
    
 	printf("%d\n",sizeof(struct aa));//打印答案是:20

对照原则,展开成员后计算。

结构体aa.m2的偏移量是4,结构体aa的sizeof是20

偏移量补充字节成员大小
004
401
534
1208

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/662431.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-18
下一篇 2022-04-18

发表评论

登录后才能评论

评论列表(0条)

保存