如何使用sizeof计算结构体所占内存大小

前言

本博文用于记录学习过程中遇到的难点知识的总结,可能涉及到许多专业内容的非专业表述。请自动忽略,重在理解。

一、各类型变量在不同运行环境中所占内存大小总结

各种变量类型在16、32、64位中所占内存空间大小

二、正文

注:下面所有例子都是在32位环境中运行
在计算结构体字节长度之前,需要明确一个概念,即补齐。简单来说,补齐就是以结构体中最大的变量类型为标准,将不满足该标准的变量类型补齐为满足该标准的变量类型。举个例子,如果结构体中有double和int成员的变量,那么对于int,就要按照double进行补齐,即8+8=16。
在这里插入图片描述我们再引入一个char类型变量:
在这里插入图片描述输出结果仍然是16,这是因为char占1字节,int占4字节,两个加起来只占5字节,用一个8字节的单元足以补齐,所以没必要再加一个单元,仍然是8+8=16。
在这里插入图片描述还是刚才的例子,只不过调整了下顺序,但结果截然不同。这是因为计算机在分配内存时是按照变量定义顺序进行的。也就是说,上例的分配过程如下:char只有1字节,补齐为8字节(假设已知结构体中最大字节长度);double为8字节,不需要补齐;int为4字节,补齐为8字节。所以最终结果为8+8+8=24。所以在定义结构体时,成员变量的定义顺序将直接影响结构体占用内存的大小。
在这里插入图片描述在这里插入图片描述将char类型变量改成指针类型,占用空间由1字节变成4字节,但总空间不变。这是因为即便char *是4,但补齐后仍然为8。

在这里插入图片描述增加一层嵌套定义,这时总长度为24,其运算过程如下:在test2结构体中,char *是4字节,补齐为8字节(因为在test中最大变量类型为double,字节长度为8);进入test,char *是4字节,补齐为8,double是8字节,不需要补齐。因此总长度为8+8+8=24。也就是说,无论我们嵌套多少结构体,我们都可以将其视为一个结构体,将内部的成员结构体中的成员变量展开来,按照变量定义的先后顺序进行计算。
在这里插入图片描述在此基础上增加一个指针类型结构体,发现总长度变为24+8=32。也就是说,对于指针类型结构体,我们不需要将其展开,而是仅仅视作一个指针类型即可。在32位中,指针类型长度就是4,因此按照之前的原则,补齐为8即可。

在这里插入图片描述引入结构体数组。上例计算过程如下:char * 是4字节,补齐为8字节(因为在test中最大变量类型为double,字节长度为8);然后先看test结构体的长度,由上文已经知道长度为16,而这样长的变量有MaxSize(大小为10)个,所以需要乘10。总长度为16×10+8=168。补充一点,如果上述数组定义成test * t[MaxSize]的形式,则视为MaxSize(10)个test * 类型,即为4×10=40字节。这时总字节变成了48。
在这里插入图片描述还有一个特别的指针类型,即结构体自我嵌套定义,这时仍然视作指针类型,长度为4。
到此为止,关于结构体长度的计算已经讲得十分透彻了,最后用一个复杂的结构体作为结束(求sizeof(test3)):
在这里插入图片描述在这里插入图片描述在这里插入图片描述我们按照结构体成员变量的定义顺序进行计算:
第一步,明确两个结构体成员变量的大小,以辅助后续运算。test为8+8=16,test2为8+16×10+8=176。
第二步,按照成员变量定义顺序进行运算。char *为4,补齐为8;单个test2位176,test2数组为176×10=1760;单个test *为4,test *数组为4×10=40;struct test3 *m,结构体自嵌套定义,其本质还是指针类型,长度为4补齐为8。
因此,总长度为8+1760+40+8=1816。
在这里插入图片描述写的不好,如果存在错误的地方,欢迎指正,谢谢!!