c语言 结构体的大小,为什么C语言中的结构体的size,并不等于它所有成员size之和?...

结构体在C语言程序开发中,是不可或缺的语法。不过,相信不少C语言初学者遇到过这样的问题:为什么结构体的 size 有时不等于它的所有成员的 size 之和呢?

36d57eddaa894d341c399d5a787daf64.png为什么结构体的 size 有时不等于它的所

C语言结构体大小等于它的所有成员大小之和吗?

举例来说,假设有结构体,它的C语言代码如下,请看:

struct x{short s;int i;char c;};

我们继续编写C语言代码,依次输出成员 s,i,c 占用内存空间的大小,相关代码很简单,请看:

struct x t;printf("%lu %lu %lu\n", sizeof(t.s), sizeof(t.i), sizeof(c));

e533127d50bf1e206178584b28ab0f90.png实际结果与我们的预期并不一致

编译并执行这段C语言代码,得到如下输出:

# gcc t.c# ./a.out 2 4 1

那么按理说,结构体 x 占用的内存空间应该等于 2+4+1=7 字节,但是似乎实际结果与我们的预期并不一致:

printf("%lu\n", sizeof(t));

上面这行C语言代码输出的结果是 12!这是怎么回事呢?

解析

程序输出的结果与我们的预期不一致,原因在于“对齐机制”。如果将结构体 x 看作是一个容器,鉴于成员 s,i,c 的长度参差不齐,C语言编译器不得不“填充”一些额外的空间,以满足“对齐机制”。

数据结构是否对齐不仅影响C语言程序的性能,有时甚至还会带来意想不到的错误,例如访问未对齐的数据,可能会导致硬件方面的问题 (SIGBUS,总线错误),导致性能下架,以及破坏一些操作的原子性等并发安全保障。

所以,C语言编译器在处理结构体时,如果没有特别的指定,一般都会填充一些字节,以确保不违背对齐机制。以上面的结构体 x 为例,初学者可能会认为它的成员在内存中的布局如下:

ac78b97a3f76c236ff0fb86886677b53.png初学者可能会认为它的成员在内存中的布

但是,如果编译器按照下面布局,处理器访问之将更加方便:

d820fcd04f079e199d5f1423c66ae709.png处理器访问之将更加方便

不过,这样排列结构体 x 的成员,会空出一些空间,对于处理器来说,小心的跳过这些空间还是有些麻烦,于是大多数C语言编译器都会像下面这样填充空穴:

4512a1374c0b3e477a151aa179c5de23.png大多数C语言编译器都会这样填充空穴

这样一来,整个结构体 x 占用内存的空间,其实就是成员 i 占用空间的 3 倍了,也即 12 字节。

事实上,我们可以通过排列结构体 x 成员的顺序,来优化其占用内存的大小,例如:

785614d5a5486e5f4427d1838c7bcadf.png通过排列结构体 x 成员的顺序,来优化

小结

本节主要讨论了C语言中结构体大小并不一定等于它所有成员大小之和的原因,应该注意,结构对齐在C语言标准中是 implementation defined,不同的C语言编译器可能选择不同的数据对齐方式,从而导致不同和不兼容的数据布局。因此,在使用不同编译器开发C语言程序时,了解编译器是如何对齐数据是很重要的。

一些编译器可以指定结构对齐的方式,例如 #pragma 语句。

74d6b4d2a66a10c780e03bc4a81b8db9.png点个赞再走吧

欢迎在评论区一起讨论,质疑。文章都是手打原创,每天最浅显的介绍C语言、linux等嵌入式开发,喜欢我的文章就关注一波吧,可以看到最新更新和之前的文章哦(最近发现有些帐号搬运我的文章并且标上原创标签,有些可耻,请注明出处!!)。

举报/反馈

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值