同一翻译单元中声明的兼容结构体类型有哪些要求?
同一翻译单元中C语言结构体类型的兼容规则解析
C11标准的相关规定
C11标准6.2.7节《兼容类型和复合类型》第1款指出:
此外,在不同翻译单元中声明的两个结构体、联合体或枚举类型,若其标签和成员满足以下要求,则为兼容类型:……
上述内容明确了不同翻译单元中结构体类型的兼容要求,那么同一翻译单元中声明的结构体类型,兼容规则是什么?
对比测试与结论
C++17标准(N4713)中有这样的说明:
例如,除标签名不同外完全相同的结构体类型在C中是“兼容”的,但在C++中是截然不同的类型。
我们可以通过一段测试代码验证C语言中的实际行为:
struct x { int x; } x; struct y { int x; } *p = &x;
使用主流C编译器以C11标准编译这段代码,得到如下警告:
$ gcc t0.c -std=c11 -pedantic -Wall -Wextra warning: initialization of 'struct y *' from incompatible pointer type 'struct x *' [-Wincompatible-pointer-types] $ clang t0.c -std=c11 -pedantic -Wall -Wextra warning: incompatible pointer types initializing 'struct y *' with an expression of type 'struct x *' [-Wincompatible-pointer-types] $ icc t0.c -std=c11 -pedantic -Wall -Wextra warning #144: a value of type "struct x *" cannot be used to initialize an entity of type "struct y *" $ cl t0.c /std:c11 warning C4133: 'initializing': incompatible types - from 'x *' to 'y *'
从测试结果可以明确:在同一翻译单元中声明的、仅标签名不同但成员完全一致的结构体类型不兼容。
补充说明
此前有讨论聚焦于“不同翻译单元中结构体类型是否真的兼容”这一问题,这里不再展开外部讨论细节。
关于链接器的疑问
针对“链接器会判断类型是否兼容”的说法,我们做了如下测试:
foo.c
struct struc1 { int x; }; int foo(struct struc1 *s) { return s->x; }
main.c
struct struc { float x; }; int foo(struct struc *s); int main(void) { return foo(&(struct struc){1.2f}); }
执行编译命令后无任何报错:
$ gcc foo.c main.c -std=c11 -pedantic -Wall -Wextra <nothing>
那么问题来了:为何链接器未报错?
内容的提问来源于stack exchange,提问作者pmor
相关产品推荐
相关产品推荐

