期望成员之间没有填充是否安全?

时间:2017-05-03 07:17:02

标签: c struct language-lawyer padding

正如C11草案所述,我可以向这两个人保证:

  1.   

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

  2.   

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

  3. 然而,如果任何两个成员之间的填充是可以接受的,那对我来说是不明确的。 这是因为,通过说第二段,标准似乎暗示填充只能在结构或联合的末尾。例如,假设int占用4个字节,< / p>

    #include <stdio.h>
    
    struct s {
        char c;
        int a;
    };
    
    int main(void) {
        printf("%d\n", sizeof(struct s));
        return 0;
    }
    

    我可以安全地得出结论:ca之间没有填充吗?

2 个答案:

答案 0 :(得分:5)

不,你不能断定会员之间没有填充。

第一句话说,

  

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

这表明成员中可以填充。实际上并不清楚在最后发生了什么。所以,为了清楚起来,第二个引用说的是

  

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

说,成员之间不能填充。根据现有成员对齐情况,它不会结束,它可能会或可能不存在。

答案 1 :(得分:0)

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

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执行两个外部总线请求来解决问题,并丢弃不需要的数据。原因是对于具有四个字节的字大小的处理器(32位架构中的典型值),没有A0和A1地址线(它们具有四条总线切片使能线,或者根本没有),并且它们访问总线以进行读取整个单词,然后丢弃他们不需要的数据。未对齐的四个字节int值将在一个地址中具有部分值,而其余地址在下一个/上一个地址中。其他架构只是触发陷阱并允许操作系统负责这一点。