关于c语言结构体大小
以下程序结果在64位ubuntu19.04以gcc编译所得
程序如下
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <stdlib.h>
4
5 struct
6 {
7 double math;
8 char name[20];
9 int id;
10 }stu;
11
12 struct
13 {
14 double math;
15 char name[20];
16 int id;
17 char lk;
18 }stu1;
19
20 struct
21 {
22 double math;
23 char name[20];
24 int chinese;
25 int ath;
26 char lk;
27 }stu2;
28
29
30 int main()
31 {
32 printf("sizeof(stu)%ld\n",sizeof(stu));
33 printf("sizeof(stu1)%ld\n",sizeof(stu1));
34 printf("sizeof(stu2)%ld\n",sizeof(stu2));
35 }
结果为
sizeof(stu)32
sizeof(stu1)40
sizeof(stu2)40
在计算结构体大小时我们需要计算偏移量,在stu1中结构体成员和为33,另外结构体中所占位数最多的基本数据类型为double,所以此时我们在计算结构体所占字节数时偏移为8的倍数,此大小为40。而不是单纯相加,stu中只是因为需要偏移后大小恰好等于其成员相加的大小,所以不需要偏移。而stu2方便大家理解的加入了所占字节数为4的int的变量数组,而其依然需要偏移到40所以其所占字节数为40。
以上所说的只是简单情况下的偏移,当结构体中出现结构体调用时问题会发生一些变化。
1 #include <stdio.h>
2
3 struct list_head
4 {
5 struct list_head *next;
6 int data;
7 };
8
9 struct stu
10 {
11 int id;
12 char name[20];
13 int math;
14 struct list_head node;
15 int ip;
16 struct list_head head;
17 char a;
18 };
19
20 int main(void)
21 {
22 struct stu s;
23
24 printf("&s = %p\n", &s);
25 printf("&s.id = %p\n", &s.id);
26 printf("s.name = %p\n", s.name);
27 printf("&s.math = %p\n", &s.math);
28 printf("&s.node = %p\n", &s.node);
29 printf("&s.ip = %p\n", &s.ip);
30 printf("&s.head = %p\n", &s.head);
31
32 printf("sizeof(struct stu) = %ld\n",sizeof(struct stu));
33 printf("size = %ld\n", (size_t)&((struct stu *)0)->node);
34
35 return 0;
36 }
由于偏移量和偏移成员与之前程序变得复杂我在这里打印了许多地址方便朋友们参考
打印出结果为
&s = 0x7ffded2cec10
&s.id = 0x7ffded2cec10
s.name = 0x7ffded2cec14
&s.math = 0x7ffded2cec28
&s.node = 0x7ffded2cec30
&s.ip = 0x7ffded2cec40
&s.head = 0x7ffded2cec48
sizeof(struct stu) = 80
size = 32
下面我们来分析一下,首先结构体中调用有单成员字节数占8及8以上的成员,所以我们偏移时需偏移至8的倍数。其次当遇到结构体中调用其他结构体时,我们直接在前一个成员计算偏移例如&s.math时此时之前成员所占字节数和为28不为8的倍数需偏移至32,之后计算内部结构大小(需计算偏移,偏移后为16)。在遇到结构体调用时同理可得偏移4个字节,最后加上之前偏移量大小为73字节需要再次偏移,所以最后结果为80字节。
ps最后一种打印方法是打印之前成员大小的一种通用性很强的方法(从内核链表里学的)分享给大家。