【问题标题】:Is it safe to expect there will be no padding between members?期望成员之间没有填充是否安全?
【发布时间】:2017-09-30 21:39:34
【问题描述】:

正如 C11 草案所述,我可以向以下两点保证:

  1. ...结构对象中可能有未命名的填充,但不是在其开头

  2. 可能有未命名的填充在结构或联合的末尾

但是,如果任何两个成员之间的填充是可以接受的,这对我来说是模棱两可的。 这是因为,通过说第二段,标准似乎暗示填充只能在结构或联合的末尾。例如,假设int在这里占用4个字节,

#include <stdio.h>

struct s {
    char c;
    int a;
};

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

我可以确定ca 之间没有填充吗?

【问题讨论】:

标签: c struct language-lawyer padding


【解决方案1】:

不,您不能断定成员之间没有填充。

第一句话说,

...可能有未命名的填充在结构对象内,但不是在其开头。

这清楚地表明成员内可以有填充。实际上并不清楚最后会发生什么。所以,为了澄清这一点,第二句话说

结构或联合的末尾可能有未命名的填充。

说,成员之间不能有填充。它不是结束的,它可能存在,也可能不存在,取决于现有的成员对齐方式。

【讨论】:

  • 为什么标准的only最后只讨论可能的填充...?我很困惑。
  • @Il-seobBae 为了便于携带,你甚至不能使用原始的int 值。
  • @Il-seobBae 我的意思是“位打包”的可移植性。您为什么甚至期望结构布局之类的东西以任何方式可移植?不同的实现不仅有不同的对齐要求,对于相同的数据类型,它们可以有不同的大小。它们甚至可以有不同的每字节位数。
  • @Il-seobBae 您在寻找固定宽度的数据类型吗?他们已经在那里了,AFAIK。
  • @supercat “质量编译器”?这完全是主观的。您在对齐差异可能会对性能产生重大影响的非 x86 架构上拥有多少经验? 同一个编译器可以根据不同的优化选项生成相同结构的不同对齐版本?
【解决方案2】:

不,您不能假设相同结构的字段之间没有填充。顺便说一句,您的示例很可能在结构的两个字段之间有一些填充:

struct s {
    char c;
    /* most probably, you'll get padding here */
    int a;
};

这样做的原因是您需要能够访问与某些架构约束一致的a 字段(例如sizeof int 地址的倍数)。英特尔处理器显然不需要这样做,但大多数其他架构强制错位以引发某种异常(你会在 unix 上看到SIGBUS 信号,通常),导致程序错误。查看Is it guaranteed that array elements in C will be stored consecutively, with no padding?,您就会对背后的问题有所了解。

无论如何,英特尔处理器通过对每个未对齐的int 执行 两个 外部总线请求并丢弃不需要的数据来解决问题。原因是对于字长为 4 字节的处理器(通常在 32 位架构中)没有 A0 和 A1 地址线(它们有四个总线片启用线,或者根本没有),它们访问总线以读取整个单词,然后丢弃他们不需要的数据。未对齐的四字节 int 值将在一个地址中具有部分值,而在下一个/前一个地址中具有其余值。其他架构只是触发一个陷阱,让操作系统来负责。

【讨论】:

    猜你喜欢
    • 2019-09-23
    • 2011-09-08
    • 2020-09-18
    • 2018-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-02
    • 2020-04-21
    相关资源
    最近更新 更多