正如C11草案所述,我可以向这两个人保证:
...结构对象中可能有未命名的填充,但不是在其开头。
在结构或联合的末尾可能有未命名的填充 。
然而,如果任何两个成员之间的填充是可以接受的,那对我来说是不明确的。 这是因为,通过说第二段,标准似乎暗示填充只能在结构或联合的末尾。例如,假设int
占用4个字节,< / p>
#include <stdio.h>
struct s {
char c;
int a;
};
int main(void) {
printf("%d\n", sizeof(struct s));
return 0;
}
我可以安全地得出结论:c
和a
之间没有填充吗?
答案 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
值将在一个地址中具有部分值,而其余地址在下一个/上一个地址中。其他架构只是触发陷阱并允许操作系统负责这一点。