C语言《结构体内存对齐与offsetof宏的使用》

目录

1.什么是内存对齐

2.offsetof的使用

3.如何内存对齐

4.为什么要有内存对齐


1.什么是内存对齐

带着这个问题我们先看一个代码

struct book
{
	char num;
	char name;
	int age;
}s1;
struct book1
{
	char num;
	int age;
	char name;
}s2;
int main()
{
	printf("%d\n", sizeof(s1));
	printf("%d\n", sizeof(s2));
	return 0;
}

可以看到,同样的成员结构体所占内存的空间确实不同的,这就涉及到了内存对齐。所谓内存对齐,就是将数据存放到一个是字的整数倍的地址指向的内存之中。cpu就可以通过这些地址在内存中访问这些数据。32(64)位的cpu一次性访问计算4(8)个字节的数据。内存对齐的本质是以空间换时间,按照内存对齐后cpu访问效率则提高,且可移植性增强。

2.offsetof的使用

介绍如何内存对齐之前需要明白offsetof宏的使用,offsetof是计算联合类型成员的地址据该类型起始地址的远近(单位为字节)的函数

 图中所示结构体s1中有偏移量为2和3的地址处无数据,这就由于内存对齐。下面讲述内存对齐的规则。

3.如何内存对齐

1.结构体的第一个成员存放在结构体变量开始位置的0偏移量处。

 2.从第二个成员开始,都要对齐到对齐数的整数倍的地址处(对齐数:成员自身大小和默认对齐数两者的较小值,其中vs环境下默认对齐数是8,linux没有默认对齐数,其对齐数为成员自身大小)。(若成员是数组,对齐数也是数组的类型与默认对齐数的最小值)

3.结构体的总大小是该结构体最大对齐数(成员对齐数的最大值)的整数倍。(包括嵌套结构体的对齐数)

4.如果是嵌套结构体,嵌套在里面的结构体对齐到自身最大对齐数的整数倍。

举个例子

 先算s2 的大小,num为第一个成员位于偏移量0处,第二个成员int对齐数为4,故需要储存在偏移量为4的整数倍处即4-7,name的对齐数1的整数倍是任意数,储存在偏移量为8处,由第三条规则结构体总大小是最大对齐数的整数倍,4的整数倍12,故补齐到11,0~11共12个字节。

 再算s1的大小(添加s2后的),s2最大对齐数4,刚好s2存于对齐数为8处(s2大小为12),且总大小为最大对齐数4的整数倍,4*5 = 20(0~19)。故s1的大小为20.

4.为什么要有内存对齐


1.平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。


2.性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。

(32(64)位的cpu一次性访问计算4(8)个字节的数据。内存对齐的本质是以空间换时间,按照内存对齐后cpu访问效率则提高,且可移植性增强。)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值