C/C++中结构体占用内存大小的计算方法

引言


结构体在C语言中虽然经常使用,但是怎么计算一个结构体占用多大的内存,很多C语言的新手都没注意过,其实C语言的语法简单,难就难在它更偏向于与底层,与内存打交道。对于嵌入式方面来说,对C语言的要求更高,因为有些硬件的内存并不像我们使用的电脑的内存那么充裕,所以需要节约内存。

结构体中同样的变量个数,却可能导致占用内存的大小不同。


例子1:

#include <stdio.h>
int main()
{
	typedef struct a
	{
		int c;
		double d;		     
		char b[10];
	}test;
	test  e;
	printf("%d", sizeof(test));
	return 0;
} 
输出的结果为:32


例子2:

#include <stdio.h>
int main()
{
	typedef struct a
	{
		double d;
		int c;		     
		char b[10];
	}test;
	test  e;
	printf("%d", sizeof(test));
	return 0;
} 

 输出的结果为:24 

只是调换了一下int c和double d的位置,就导致了前者比后者多占用了8个字节的内存。这只是一个小例子。那么,结构体中到底怎么计算内存的呢。

计算规则

首先需要介绍<b>有效对齐值</b>:每个平台上的编译器都有默认对齐系数n,可以通过#pragma pack(n)来指定。有效对齐值就等与该对齐系数和结构体中最长的数据类型的长度两者最小的那一个值,比如对齐系数是8,而结构体中最长的是int,4个字节,那么有效对齐值为4。

结构体的内存计算方式遵循以下规则:

1.数据成员对齐规则:第一个数据成员放在offset为0的地方,以后的每一个成员的offset都必须是该成员的大小与有效对齐值相比较小的数值的整数倍,例子1中第一个数据成员是int 型,第二个是double,有效对齐值为8,所以double的起始地址应该为8,所以第一个int加上内存补齐用了8个字节

2.结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从其内部有效对齐值的整数倍地址开始存储。(比如struct a中存有struct b,b里有char, int, double,那b应该从8的整数倍开始存储)

3.收尾工作:结构体的总大小,必须是其有效对齐值的整数倍,不足的要补齐。

有了这些规则,再来看上面的两个例子。

例子1中,int为第一个数据成员,所以下一个存储的起始位置是4,但是double占8个字节,按规则一,不满足8的倍数,填充到16,char一共有10个字节(数组在内存中的表示会分解成单个的),即总共26,进行收尾工作,有效对齐值为8,26不满足8的倍数,填充到32。

例子2中,double为第一个数据成员,所以下一个存储的起始位置是8,按规则一,占用了12个字节,char有10个字节,一共用了22个字节,进行收尾工作,该结构体中有效对齐值为8,22不满足8的倍数,填充到24。

例子

下面给你一个question,考察你是否懂了上面的规则

#include <stdio.h>
#pragma pack(8)
int main()
{
	struct Test
	{
		int a;
		//long double大小为16bytes
		long double b;		     
		char c[10];
	};
	printf("%d", sizeof(Test));
	return 0;
} 


#include <stdio.h>
#pragma pack(16)
int main()
{
	struct Test
	{
		int a;
		//long double大小为16bytes
		long double b;		     
		char c[10];
	}
	printf("%d", sizeof(Test));
	return 0;
}


如果你计算得出的答案分别为40和48,那我相信你就懂了内存对齐的奥秘了。



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值