c中的结构标签兼容性
structure tag compatibility in c
我读到从 C99 开始,在不同文件中定义的两个完整 struct
必须具有相同的标记才能兼容。
所以我写了下面的代码:
file1.c:
/* file1.c */
#include <stdio.h>
typedef struct tag1 { int foo; } type1;
type1 a;
void func(void);
int main() {
printf("a.foo : %d\n", a.foo);
func();
printf("a.foo : %d\n", a.foo);
return 0;
}
file2.c:
/* file2.c */
typedef struct tag2 { int foo; } type2;
type2 a;
void func(void) {
a.foo = 100;
}
并期望两个 a
被认为是不同的,因此两个 printf
都打印 a.foo : 0
但输出是:
a.foo : 0
a.foo : 100
这是为什么?
关于类型问题,C标准中的规定是这样的:
- 如果你在两个文件中使用相同的结构标签声明
a
,那么你的程序将工作(在这个尊重)。
请注意,C 标准并未说明如果违反“如果”部分会发生什么情况。在那种情况下,C 标准并没有说你的程序会工作,它没有说你的程序不会工作,它没有说会有错误信息,它没有说不会有错误信息。它什么也没说。
程序中还有一个问题:type1 a;
和type2 a;
是a
的暂定,根据C标准,解决定义。那么a
定义在多个翻译单元中,违反了C 2018 6.9 5:
… If an identifier declared with external linkage is used in an expression (other than as part of the operand of a sizeof
or _Alignof
operator whose result is an integer constant), somewhere in the entire program there shall be exactly one external definition for the identifier; otherwise, there shall be no more than one.
但是,假设您的 C 实现定义了这些以将它们解析为单个对象,就像 Unix 上的 C 实现通常所做的那样。我们只会考虑类型问题。
那么您正在使用两个不兼容的类型访问对象 a
。这违反了 C 2018 6.5 7:
An object shall have its stored value accessed only by an lvalue expression that has one of the following types:…
其中 none 列出的类型在这种情况下得到满足。 C 2018 4 2 告诉我们这个违规的后果是什么:
If a "shall" or "shall not" requirement that appears outside of a constraint or runtime-constraint is violated, the behavior is undefined…
而 C 2018 3.4.3 告诉我们这意味着什么:
behavior, upon use of a nonportable or erroneous program construct or of erroneous data, for which this document imposes no requirements
就是这样:由于类型冲突,C 标准对 C 实现没有任何要求。该标准允许您的实现(编译器、链接器、库、操作系统、硬件以及构建和 运行 C 程序所需的任何其他东西)接受您的程序,拒绝您的程序,运行 您的程序,拒绝 运行 你的程序,警告你,不警告你,让你的程序行为不端,等等。该标准对必须发生的事情只字不提。
我读到从 C99 开始,在不同文件中定义的两个完整 struct
必须具有相同的标记才能兼容。
所以我写了下面的代码:
file1.c:
/* file1.c */
#include <stdio.h>
typedef struct tag1 { int foo; } type1;
type1 a;
void func(void);
int main() {
printf("a.foo : %d\n", a.foo);
func();
printf("a.foo : %d\n", a.foo);
return 0;
}
file2.c:
/* file2.c */
typedef struct tag2 { int foo; } type2;
type2 a;
void func(void) {
a.foo = 100;
}
并期望两个 a
被认为是不同的,因此两个 printf
都打印 a.foo : 0
但输出是:
a.foo : 0
a.foo : 100
这是为什么?
关于类型问题,C标准中的规定是这样的:
- 如果你在两个文件中使用相同的结构标签声明
a
,那么你的程序将工作(在这个尊重)。
请注意,C 标准并未说明如果违反“如果”部分会发生什么情况。在那种情况下,C 标准并没有说你的程序会工作,它没有说你的程序不会工作,它没有说会有错误信息,它没有说不会有错误信息。它什么也没说。
程序中还有一个问题:type1 a;
和type2 a;
是a
的暂定,根据C标准,解决定义。那么a
定义在多个翻译单元中,违反了C 2018 6.9 5:
… If an identifier declared with external linkage is used in an expression (other than as part of the operand of a
sizeof
or_Alignof
operator whose result is an integer constant), somewhere in the entire program there shall be exactly one external definition for the identifier; otherwise, there shall be no more than one.
但是,假设您的 C 实现定义了这些以将它们解析为单个对象,就像 Unix 上的 C 实现通常所做的那样。我们只会考虑类型问题。
那么您正在使用两个不兼容的类型访问对象 a
。这违反了 C 2018 6.5 7:
An object shall have its stored value accessed only by an lvalue expression that has one of the following types:…
其中 none 列出的类型在这种情况下得到满足。 C 2018 4 2 告诉我们这个违规的后果是什么:
If a "shall" or "shall not" requirement that appears outside of a constraint or runtime-constraint is violated, the behavior is undefined…
而 C 2018 3.4.3 告诉我们这意味着什么:
behavior, upon use of a nonportable or erroneous program construct or of erroneous data, for which this document imposes no requirements
就是这样:由于类型冲突,C 标准对 C 实现没有任何要求。该标准允许您的实现(编译器、链接器、库、操作系统、硬件以及构建和 运行 C 程序所需的任何其他东西)接受您的程序,拒绝您的程序,运行 您的程序,拒绝 运行 你的程序,警告你,不警告你,让你的程序行为不端,等等。该标准对必须发生的事情只字不提。