结构体和联合体名称冲突

3
我写了一个简单的测试程序并尝试使用它: ```

我写了一个简单的测试程序并尝试使用它:

```
union FLT { ... };
struct FLT { ... };

但编译器报错了关于命名冲突的问题。

因为在C语言中,你需要在标签名称前使用structunion,那么它们为什么会发生冲突呢?

我的意思是,当我们想要声明一个类型为struct FLT、名称为num的变量时,我们会使用

struct FLT num;

如果我们想要使用一个名为diffnum,类型为union FLT的变量,我们需要使用以下语法:

union FLT diffnum;

那么为什么编译器不能区分它们呢?

顺便说一下,我测试了MinGW和VC,如果你需要知道的话。

更新

union FLOAT {
        float value;
        unsigned int bits;
        unsigned char bytes[4];
};
struct FLOAT {
        unsigned int sign;
        unsigned int exponent;
        unsigned int significand;
};
union FLOAT num;
struct FLOAT num_parts;

我正在使用这段代码进行浮点运算测试。

有趣的是,在C++中声明这样的变量时,你不需要写“struct”或“enum”。 - JFMR
是的,没错,这也是我觉得这种行为很奇怪的原因之一。C++并不强制要求它们的使用,所以当C强制要求它们的使用时,为什么编译器不能或不会利用这个额外的信息呢? - m0h4mm4d
3
ISO/IEC 9899:2011 §6.2.3中提到,结构体、共用体和枚举类型的标签(通过跟随任意32个关键字“struct”、“union”或“enum”进行消除歧义);注释32说:尽管有三种可能,但只有一个标签名称空间。因此,标准承认了将结构体、共用体和枚举类型的标签分别放置在不同名称空间的可能性,但是有意选择不将它们分开,这可能是基于先前的技术(没有编译器将它们分开)。 - Jonathan Leffler
@FelixPalmen:C++中存在“struct stat{...}”和函数“int stat(const char *filename, struct stat *sb)”的问题,这让生命变得有趣。这就是你所指的吗? - Jonathan Leffler
1
@StoryTeller:这个问题在 Stroustrup 的《设计与演化》第2.8.2节“结构标签 vs 类型名称”(第48页)中得到了指出。 - Jonathan Leffler
显示剩余6条评论
1个回答

7

它们会发生碰撞,因为所有“标记类型”在标记方面共享一个命名空间。

C11 6.2.3 标识符的名称空间(N1570草案)

如果在翻译单元中的任何时刻可见特定标识符的多个声明,则语法上下文将消除引用不同实体的用法。因此,对于各种类别的标识符,有单独的名称空间,如下所示:

  • 标签名称(通过标签声明和使用的语法来消除歧义);
  • 结构、联合和枚举的标记(通过跟随关键字struct、union或enum来消除歧义);
  • 结构体或联合体的成员;每个结构体或联合体都有一个成员的单独名称空间(通过使用表达式访问成员的.或->运算符的类型来消除歧义);
  • 所有其他标识符,称为普通标识符(在普通声明符或作为枚举常量中声明)。

2
一个“为什么”的问题在SO上并没有太多意义,这将是完全推测性的。 - user2371524
3
@m0h4mm4d - 我不能因为我不在定义标准的委员会上。这就是他们定义的方式(自1989年以来没有改变)。 - StoryTeller - Unslander Monica
2
“有什么想法吗?”怎么样进行一些纯粹的猜测呢?也许第一个编译器将已声明的structunion的信息存储在一个公共数据结构中,唯一的区别是对于union中每个字段存储的偏移量为0,而对于struct则为前面字段大小之和。 - Warren Weckesser
2
早期的 C 编译器非常简单。这可能只是为了避免每种类型都需要单独的符号表。 - Barmar
2
这取决于你想要使用多早的“早期编译器”。在第一个支持结构的版本中,结构成员的名称必须在所有结构中唯一,并且您可以使用相同类型和偏移量的名称在不相关的结构中进行各种操作。不久之后,每个结构(或联合)都为其成员获得了单独的命名空间,这使得编写可靠的代码变得更加容易。 - Jonathan Leffler
显示剩余12条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接