结构体的内存大小计算

一、对齐规则

1、开头:结构体的第一个成员在结构体变量偏移量为0的地址处

列如:

#include<stdio.h>

struct Type
{
	int a;
    int b;
	char c;
}Example;

int main()
{
	printf("%p\n%p", &Example, &Example.a);
	return 0;
}

运行结果为

说明结构体Example的第一个成员a的起始地址和结构体本身的起始地址是一样的

2、中间:其他成员要对齐到每个成员各自选取的对齐数的整数倍的地址处
什么是对齐数?

对齐数就是相对于结构体起始地址的地址偏移量,那么第一个成员的选取的对齐数就是0

选取的对齐数的取值和该成员的类型和默认对齐数有关:

VS编译器的默认对齐数为8,成员的对齐数和它的类型所占用的字节数相等,比如在32位平台上成员b的类型是int占用4个字节,那么它的对齐数是4;而成员c的类型是char占用1个字节,那么它的对齐数是1

选取对齐数时,将默认对齐数和成员本身的对齐数比较后,选取较小的那个对齐数,比如成员b的对齐数4小于默认对齐数8,所以选取的对齐数为4;成员c的对齐数1小于默认对齐数8,所以选取的对齐数为1

简单来说,成员所占的字节数小于默认对齐数,选择所占字节数的值为对齐数(嵌套结构体的情况除外,下面会讲到)

修改默认对齐数
//修改默认对齐数为4
#pragma pack(4)
内存占用情况

成员a已经占据4个字节,成员b只能从地址偏移量为4的地方开始放置,而4正好是它选取的对齐数4的整数倍,所以成员b放在偏移量为4的地址处。同理,成员a、b连续存放占用了8个字节,所以成员c只能从地址偏移量为8的地方开始放置,而8正好是它选取的对齐数1的整数倍,所以成员c放在偏移量为8的地址处

存放情况如下:

那么有没有成员之间有内存浪费的情况呢,请看下列的例子:

struct Type
{
	int a;
	char b;
	short c;
}Example;

根据上面可知,a作为第一个成员,对齐到结构体的起始地址,b的对齐数为1,c的对齐数为2

那么他们的存放情况如下:

因为成员c选取的对齐数为2,而5不是2的整数倍,所以成员c不能放置在偏移量为5的位置,向后找到6,它是2的整数倍,所以成员c放置在偏移量为6的位置

成员b和成员c之间的空间就被浪费掉了

当然,这种浪费是有意义的,它可以让计算机读取数据时速度更快

3、结尾:结构体的总大小为最大对齐数的整数倍

最大对齐数就是一个结构体里所有成员中选取的最大对齐数(不包括默认对齐数)

看一下上面的第一个例子:

struct Type
{
	int a;
    int b;
	char c;
}Example;

成员a选取的对齐数为4,成员b选取的对齐数为4,成员c选取的对齐数为1,所以最大对齐数为4

那么这个结构体总共要占用多少内存呢?

我们知道它的内存占用情况是:

9不是最大对齐数4的整数倍,所以向后找到10,10也不是最大对齐数4的整数倍........

一直找到12符合条件,所以这个结构体所占内存的大小是12字节

struct Type
{
	int a;
	int b;
	char c;
}Example;
int main()
{
	printf("%d\n", sizeof(Example));
	return 0;
}

将上述结构体大小进行打印,结果为:

4、如果结构体中嵌套了结构体,嵌套的结构体对齐到自己的最大对齐数的整数倍处,嵌套的结构体作为成员选取的对齐数和自己的最大对齐数相等

怎么理解呢?我们先来看看嵌套的结构体,它的具体情况如下:

struct Son
{
	int a;
	int b;
	char c;
};

它的最大对齐数为:4

它所占用的内存(字节)为:12

我们再看看嵌套了它的结构体的具体情况:

struct Father
{
	int b;
    struct Son a;
	char c;
};

a作为成员,它所占的字节数为12,大于默认字节数8,按照之前的规则它选取的对齐数应该是8,那么结构体类型Father的最大对齐数应该为8

但是它是一个结构体,它选取的对齐数就是自己的最大对齐数,也就是上面的4,那么结构体类型Father的最大对齐数实际上为4

结构体类型Father的内存占用情况如下:

嵌套结构体a的最大对齐数为4,4正好是它的整数倍,所以对齐到4

而结构体类型Father的最大对齐数为4,所占用的内存大小应该是20个字节

二、总结

成员自身的对齐数和默认对齐数      决定     成员选取的对齐数      决定     最大对齐数

  • 12
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值