[C语言](详细)结构体的内存对齐(规则、存在原因、默认对齐数的修改等+实例分析)

总目录
1.结构体内存对齐的规则
2.实例图文分析
3.为什么存在结构体内存对齐(+实例分析)
4.修改默认对齐数
5.结构体成员的排序
6.最后

1.结构体内存对齐的规则

1.第一个成员在结构体变量为0的地址处

2.其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处
对齐数=编译器默认的对齐数与该成员大小的较小值

3.结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍

4.如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍数,结构体的总大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍

(vs的默认对齐数为8,linux没有默认对齐数)

2.实例图文分析

这里我们使用vs进行演示
例①
在这里插入图片描述

>由规则1 “第一个成员在结构体变量为0的地址处”,故c的位置在0地址处(橙色部分),又因为是char类型,只占第一个字节
>由规则2,该成员变量为int类型,大小为4个字节,比vs默认对齐数8要小,故i对齐到对齐数4的整数倍即下标为4的位置(绿色部分),并向下占用4个字节
>同理,d为double类型,大小与默认对齐数相同,故从i的结束位置向下找8的整数倍数,并占用8个字节
>蓝色部分即为结构体内存对齐遵循规则浪费的空间

执行程序的结果如下
在这里插入图片描述

>照应规则3: 由结果值为16,该结构体的最大对齐数为8,结构体总大小为16,为最大对齐数的整数倍

例②
在这里插入图片描述

>同例①一样,c1的位置从S2的起始位置0处开始
>由例①知,struct S1 s1的大小为16,大于默认对齐数,则对齐数为较小值8,故从对齐数的整数倍下标为8的地址处开始,并向下占用16个字节
>d1的大小是8个字节,与默认对齐数一致,故向下取8的整数倍,而24恰好为8的整数倍,则从24开始向下占用8个字节
>蓝色部分即为结构体内存对齐遵循规则浪费的空间

执行程序的结果
在这里插入图片描述

>照应规则4,例②嵌套了结构体(S1),且嵌套的结构体(S1)对齐到自身成员内最大对齐数8的位置,而结构体(S2)的总大小为32,恰好为S1的整数倍

3.为什么存在结构体对齐

大多参考资料说法:

1.平台原因(移植原因):并不是所有的硬件平台都能访问任意地址的任意数据,一些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
2.性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。因为,当访问未对齐的内存时,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。

书面语当然难以理解,举个例子
在这里插入图片描述

>上图为存在内存对齐,下图不存在内存对齐,假设系统一次读取4个字节
>当读取i的时候,上图先读取前四个块,再读取后四个块,一次可以读完i
>而下图第一次读前四个块,第二次读后四个块,将i分两次读完

可以看出内存对齐后的效率有所提升,由此可以得出结论
结构体的内存对齐是拿空间换取时间的做法

4.修改默认对齐数

不多说,看代码

#include <stddef.h>
#pragma pack(2)//修改默认对齐值
struct S
{
	char c1;
	int i;
	char c2;
};
#pragma pack()//结束对默认对齐数的修改

int main()
{	
	printf("%d\n", sizeof(struct S));
	return 0; 
}

>上述代码块,在一定范围内将默认对齐数改为了2

5.结构体成员的排序

一个小建议,当使用结构体的时候可以适当的调整结构体成员的排序,因为不同的排序可能导致结构体的总大小有所差异,正确的排序可以占用更少的大小
简单举个例子

struct S1
{
	char c1;
	int i;
	char c2;
}s1;

struct S2
{
	char c1;
	char c2;
	int i;
}s2;

void main()
{
	printf("%d\n", sizeof(s1));//12
	printf("%d\n", sizeof(s2));//8
}

6.总结

如果能帮助到你的话不妨点个赞

学习路上一路加油!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值