我们都知道,利用sizeof可以直接计算得出,那么具体是如何得出这些答案的呢,我将通过代码和四步规则法结合来做演示,如下述代码所示:
#includetypedef struct Test { char a; //1 char b; char c; }; int main() { printf("%d", sizeof(Test)); }
代码运行的结果为3,从代码中我们可以直接的看出是3个char类型的相加,但是并非所有的结构体大小都是通过类型相加来求得的,继续向下看:
#includetypedef struct Test { char a; //1 double b;//8 int c; //4 }; int main() { printf("%d", sizeof(Test)); }
将结构体中的成员类型改变后,结构的大小并非是所谓的类型所占字节之和,上述代码的运行结果为24,为了进一步解释该种现象,我们引出了字节对齐(内存对齐)的概念;
这里给出一种计算结构体大小的规则方法:
一、基本数据类型的对齐值=自身所占空间的大小
先写出结构体成员变量的类型大小,以上述代码为例,char类型1个字节,double类型8个字节,int类型4个字节,所以该结构体的大小肯定不会小于它们的类型所占字节之和≥13;
二、自定义类型的对齐值=内部成员最大的空间
显而易见,double是最大的类型,字节为8个,所以该结构体Test的对齐值即为8,同时我们要求成员对齐后的类型之和为结构体对齐值的整数倍,每个类型依次和下一个类型对齐,在上述代码中,char类型和double类型对齐,故char类型补齐为1+7;而现在的类型之和为8+8+4=20;20不是8的整数倍,所以,需在int的类型上继续加4,此时的结果就是该结构体的大小.
由此可见,结构体的大小是与成员变量的顺序排列有关;
#includetypedef struct Test { char a; //1+3 int c;/ //4 double b;//8 }; int main() { printf("%d", sizeof(Test)); }
在上述代码中,调换int 类型和double类型后,结构体的大小发生了变化,由之前的24转变成了16,所以我们从中也得出,要想结构体的大小为最小,我们可以按照所占字节大小来依次排列成员变量,即可以有效节约内存;
三、程序的指定对齐值 #pragma pack(n),n必须是2的幂次方
那么结构的的对齐值可以改变吗,在这里我们认为是可以的,只需要用一个简单地预处理便可以实现:
#pragma pack(n)//n为自己设定的对其值
#pragma pack()//取消该预处理;
四、程序的有效对齐值=程序有效对齐值和自身对齐值的较小值
怎么理解呢,请看下面的代码
#include#pragma pack(4) typedef struct Test { char a; //1+1 short b; //2 int c; //4 }; int main() { printf("%d", sizeof(Test)); }
按照规则三所说的,此时的运算结果应该为12,但事实并非如此,运行结果为8,由此,我们引入了规则四,此时结构的对齐值仍然为4;
最后用一道例题来检验一下对该规则的掌握:
#includetypedef struct Test { short a; //按8字节对齐 2+6 struct { int b; //4+4 double c;//8 char e; //1+7 }; int d; //4+4 }Test; int main() { printf("%d", sizeof(Test)); }
运行结果为40;
先检验学习成果,该结构体内部的结构体大小为24;需要注意的是该结构的对齐值为成员变量中结构体中的对大类型值,而不是内部结构体的大小,故short类型应该与8对齐为2+6; 8+24+4=36,36不是8的整数倍,故将int类型补齐为4+4;所以最终结果为8+24+8=40
如果上述内容对你有帮助,别忘了点赞+关注哦!,当然有问题欢迎评论区一起探讨^_^



