面试这个没有答出,看了许多大佬文章,总结写篇自己能看懂的文章,不足之处可评论
结构体计算要遵循字节对齐原则
结构体默认的字节对齐一般满足三个准则:
-
结构体变量的首地址能够被其最宽基本类型成员的大小所整除;
-
结构体每个成员相对于结构体首地址的偏移量(offset)都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节(internal adding);
-
结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节(trailing padding)
C语言常用数据类型所占的字节数
具体可参考:https://zhuanlan.zhihu.com/p/98674721
- 16位编译器:char *(指针变量):2个字节(寻址空间为216,所以为两个字节)
- 32位编译器:char *(指针变量):4个字节
- 64位编译器:char *(指针变量):8个字节
提示:以下是本篇文章统一参考32位
即:
char : 1
unsigned char : 1
short : 2
unsigned short : 2
int : 4
unsigned int : 4
long : 4
long long : 8
float : 4
double : 8
…
一、计算方法
1.找出成员变量中最大的字节
2.以这个最大字节为准,向下画(无限)表格
3.按结构体内成员变量顺序往下填充
二、计算举例
普通①
代码如下(示例):
struct S
{
double a; //double占8
char b; //char占1
int c; //int占4
};
按照上面的计算方法:
1.找出成员变量中最大的字节
看注释,double占的最大,为8,
2.以这个最大字节为准,向下画(无限)表格
每一行有8个格子,向下是无限的(现在都为空)
3.按结构体内成员变量顺序往下填充
①先是double :8个字节(涂8个格子)(刚好占满一行)
②后是char :1个字节(涂1个格子)(因为第一行涂满了,只能从第二行开始涂)
③最后是int : 4个字节(涂4个格子)(第二行再涂4个也没有满,就涂第二行)
(注:这4个格子是一个整体,不能分,必须在同一行)
现在就涂完了此结构体内所有的成员变量,看一看格子,涂了2行,
那此结构体大小就是2(行)*8(成员变量重最大字节)=16个字节
普通②
代码如下(示例):
struct S
{
char a; //char占1
short b; //short占2
char c; //char占1
};
按照上面的计算方法:
1.找出成员变量中最大的字节
看注释,short占的最大,为2,
2.以这个最大字节为准,向下画(无限)表格
每一行有2个格子,向下是无限的(现在都为空)
3.按结构体内成员变量顺序往下填充
①先是char :1个字节(涂1个格子)(此行还空一个格子)
②后是short :2个字节(涂2个格子)
(因为第一行只剩一个格子,代表short的两个格子是一个整体,不能分开,所以只能从第二行开始涂)
③最后是char : 1个字节(涂1个格子)(第二行已经涂满了,从第三行开始涂)
(注:必须按顺序涂,只能涂第三行,不能再涂第一行的那个空格)
现在就涂完了此结构体内所有的成员变量,看一看格子,涂了3行,
那此结构体大小就是3(行)*2(成员变量重最大字节)=6个字节
普通③
代码如下(示例):
struct S
{
char a; //char占1
char b; //char占1
short c; //short占2
};
按照上面的计算方法:
看注释,short占的最大,为2,
举了2个例子之后直接开涂
先是char(涂1),后char(涂1,因为第一行没有满且可完整的图上整个char,就涂第一行),再后short(第一行满了,涂第二行)
那此结构体大小就是2(行)*2(成员变量重最大字节)=4个字节
普通④
代码如下(示例):
struct S
{
int a; //int占4
char b; //char占1
int c; //int占4
};
此结构体大小为:3*4=12
结构体内有数组
代码如下(示例):
struct s{
char a; //1
int b; //4
char str[10]; //10个1
};
char str[10]看成10个char,即最大为4,第一行涂1格,第二行涂4格,10个char(因为是char:1,所以可往下占满涂),能涂3行,其中第三行空2个格子,
则此结构体大小为5*4=20
结构体内有另一个结构体
当结构体成员变量是另外一个结构体时,只要将 “结构体中除了内嵌结构体的大小” 与 “内嵌结构体作为整体的大小” 相加就行
代码如下(示例):
struct A{
char a; //1
int b; //4
struct B{
char c; //1
int d; //4
};
float e; //4
};
若没有结构体B,则结构体A的大小为34=12,
B的结构体大小为24=8
则此结构体A(有B)的大小为12+8=20
结构体内有联合体
只要将 “结构体中除了内嵌联合体的大小” 与 “内嵌联合体的大小” 相加就行
联合体大小就是成员中最大类型的大小,(此例联合体成员中最大类型的大小为4)
代码如下(示例):
struct A{
char a; //1
int b; //4
union{
char c; //1
int d; //4
};
};
若没有联合体,则结构体A的大小为2*4=8,
联合体大小为4
则此结构体A的大小为8+4=12
总结
最好把小的放前面呗,可以避免不必要的内存消耗