计算结构体大小笔记(C语言)

面试这个没有答出,看了许多大佬文章,总结写篇自己能看懂的文章,不足之处可评论

结构体计算要遵循字节对齐原则

结构体默认的字节对齐一般满足三个准则:

  1. 结构体变量的首地址能够被其最宽基本类型成员的大小所整除;

  2. 结构体每个成员相对于结构体首地址的偏移量(offset)都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节(internal adding);

  3. 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节(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的结构体大小为2
4=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

总结

最好把小的放前面呗,可以避免不必要的内存消耗

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值