C 为什么结构/联合兼容性要求标记和名称相等?

C 为什么结构/联合兼容性要求标记和名称相等?,c,struct,c99,C,Struct,C99,C99标准在第6.2.7.1节中使用以下语言: 如果在单独的翻译单元中声明的两个结构、联合或枚举类型的标记和成员满足以下要求,则它们是兼容的:如果其中一个使用标记声明,则另一个应使用相同的标记声明。如果两者都是完整类型,然后,以下附加要求适用:其成员之间应存在一对一的对应关系,以便每对对应成员使用兼容类型声明,,并且如果对应对中的一个成员使用名称声明,则另一个成员使用相同名称声明。对于两个结构,应按照相同的顺序声明相应的构件。对于两个结构或接头,相应的位字段应具有相同的宽度。对于两个枚举,相应的

C99标准在第6.2.7.1节中使用以下语言:

如果在单独的翻译单元中声明的两个结构、联合或枚举类型的标记和成员满足以下要求,则它们是兼容的:如果其中一个使用标记声明,则另一个应使用相同的标记声明。如果两者都是完整类型,然后,以下附加要求适用:其成员之间应存在一对一的对应关系,以便每对对应成员使用兼容类型声明,,并且如果对应对中的一个成员使用名称声明,则另一个成员使用相同名称声明。对于两个结构,应按照相同的顺序声明相应的构件。对于两个结构或接头,相应的位字段应具有相同的宽度。对于两个枚举,相应的成员应具有相同的值。(增加重点)

特别是,此规则使这两个布局相同的
struct
s不兼容,因为它们的标记和成员名称不匹配:

struct x_type {
    int x;
};

struct y_type { // << Different tag
    int y;      // << Different member name
};
结构x_类型{ int x; };
struct y_type{//您引用的文本不是指与布局兼容的类型,而是指同一类型的类型。该规则是C如何定义一个类型的两个定义是否为同一类型的有效重新定义

在您的示例中,
x_-type
y_-type
不兼容是非常正确的,因为它们肯定不描述相同的类型!如果它们兼容,则意味着调用
void foo(struct x_-type*)
使用类型为
struct y_type*
的参数将是有效的,这当然不是目的

你引用的文本和下面的段落是C++ ODR的C等价物,要求标签和成员名称相同,类似于[Basic .DEF.ODR]: 给定在多个翻译单元中定义的名为

D
的实体

-
D
的每个定义应包含相同的令牌序列;并且
-在
D
的每个定义中,根据3.4查找的对应名称应指在
D
定义中定义的实体,或应指过载解析(13.3)和部分模板专门化匹配(14.8.3)后的相同实体,[…]


对于编译后的代码,我也看不出有什么理由,但可能是为了解释器?可能是为了更严格的类型检查?如果你想比较两个对象,让它们的类型完全相同..当然,出于通常的原因,这会使编译器编写者的工作更容易。很早的C版本还没有标记,结构成员被添加到唯一的symbo中l表。当它被添加时,硬件仍然是非常普通的。结构分配将挑战建议的兼容类型的宽松定义的直觉。@HansPassant:“C的早期版本还没有标签”你能提供一个引用吗?AFAIK,<代码> TyPulfFu/Cuff>后来被添加了,那么不同的<代码>结构> <代码> s已经被区分了吗?重载的存在使C++的情况非常不同,而且很容易理解。“如果…”在一个翻译单元中定义
void foo(struct x_type)
,则在单独的翻译单元中声明的两个结构、并集或枚举类型是兼容的,然后声明
extern foo(struct y_type)
在另一个翻译单元中,进行调用,这是未定义的行为,但我想不出一个技术原因,为什么这不能与任何C编译器一起工作。事实上,6.2.7.1规则并没有描述技术上的工作原理,因为正确的字节恰好位于正确的偏移量,它描述了类型系统如何决定两个类型是否为a你是否相同,这是类型系统的一个重要组成部分。如果没有这一点,最好不要麻烦有一个类型系统:)换句话说,你是说这是出于哲学的原因,而不是技术的原因?我想这是公平的,尽管这不是C语言设计者的特点,他们的目标似乎是结合是的。C很久以前就不再是高级汇编语言了。@dasblinkenlight:有些编译器,如gcc,会认为通过
struct x_type*
类型的指针进行的访问不可能影响
struct y_type
的任何成员,即使er名称和类型完全匹配。即使一个包含两种结构类型的联合声明是可见的,它也会做出这样的假设。我不知道在后一种情况下,这种行为如何被称为兼容,但gcc的作者似乎认为是这样的。