9.5.6 在命名命名空间或全局命名空间中声明的匿名联合应声明为静态的。
为什么是这样?
假设匿名联合不需要声明为静态的,并且编译器遇到这两个翻译单元(在预处理之后):
文件1:
union {
int a;
char b;
};
// Further contents referring to a and b
文件2:
union {
int a;
char b;
};
// Further (different) contents referring to a and b
这两个联合是同一个对象,还是应该是不同的对象?
我认为,为了避免此类无法回答的问题,已决定必须将命名空间范围的匿名联合声明为静态的。
我的猜测是,如果允许以非静态方式定义联合,它可能会违反ODR(一个定义规则)
我最好的猜测:
如果它是非静态的,它可以被其他代码引用。但是其他代码会怎么称呼它?它是匿名的。因此,需要将匿名联合限制在某个本地范围内;因此,它应该被声明为静态的。
但这只是一个猜测。语言设计师可以按照他们想要的方式设计事物。有时他们的选择是武断的,只是因为必须做出一些选择。
$9.5/5- 形式为 union { member-specification } 的联合;称为匿名联合;它定义了一个未命名类型的未命名对象。
我猜它应该是静态的,以便可以根据全局静态对象的规则初始化对象。如果它不是静态的并且对象没有名称,那么如何初始化它?
编辑2:
在重新考虑...
匿名工会的成员具有内部联系。此外,默认情况下,全局名称具有外部链接,除非它们具有内部链接。如果匿名联合的名称具有外部链接,则匿名联合的成员不可能具有内部链接。因此,匿名联合使用“静态”存储类说明符声明,以便匿名名称本身具有内部链接。
静态要求从来没有正当理由,应该将其删除。编译器确实并且应该将联合中的多个元素视为共享相同地址的多个单独的全局变量。实际上,这意味着编译器允许将多种类型应用于同一地址。由于全局匿名联合的范围是全局范围,因此在匿名联合中命名元素的规则应该(并且是)与命名全局变量的规则相同。即匿名联合元素名称必须是唯一的。至于联合的初始化——联合的初始化和简单变量的初始化没有区别。关于静态联合的另一点——联合的值和类型取决于时间。请注意,一次只有一个值可以占用联合,而不管其中的元素数量如何。声明联合开始的原因是允许相同的地址在不同的时间动态地用于不同的类型。这就是为什么静态联合是用词不当而一些编译器简单地忽略它的原因。