C有像C++这样的一个定义规则吗?

Tre*_*vor 17 c c++ global-variables variable-declaration language-lawyer

最近,我发现有些情况绝对会违反C++的ODR,但在C编译器中会编译好.

例如,这个奇怪的场景(和我一起):

来源1

int var_global=-3;
Run Code Online (Sandbox Code Playgroud)

来源2

#include <stdio.h>
#include <conio.h>

unsigned int var_global;

int main() {    

 printf("%d \n",var_global);
 getch();
 return 0;

}
Run Code Online (Sandbox Code Playgroud)

我有打印结果-3(即使在源2 var_globalunsigned)并且没有关于重新定义的错误var_global.

我知道C与C++有不同的规则,但我认为它不是那么不同.

我有谷歌并阅读了很多结果,但没有 C++ 这样的官方结果.

所以问题是:

C有像C++这样的一个定义规则吗?

和:

什么叫官方?

我需要它与C++规则进行比较,这样我才能更深入地理解这两种语言.

p/s:我使用Visual Studio 2010编译上面的代码.

Sou*_*osh 14

我认为您正在寻找的是C11标准的兼容型和复合型 §6.2.7 ,(强调我的)

引用同一对象或函数的所有声明都应具有兼容类型 ; 否则,行为未定义.

并且与兼容类型有关,

如果类型相同,则两种类型具有兼容类型.

根据你的情况,intunsigned int不兼容的类型.因此未定义的行为.

我想补充一点清晰的,在你的源2,unsigned int var_global;是一个声明,它不匹配其他declatation(和定义),所以,这是UB.

那说,一个声明就好

 printf("%d \n",var_global);
Run Code Online (Sandbox Code Playgroud)

将始终认为参数为%d类型int.如果类型和格式说明符不匹配,您将再次调用未定义的行为.


编辑:

编辑后,答案是,用于-fno-common获得所需的错误.(我相信,失踪extern是你所困扰的).

引自在线GCC手册,

-fno-common

在C代码中,控制未初始化的全局变量的放置.Unix C编译器传统上允许通过将变量放在公共块中而在不同的编译单元中对这些变量进行多种定义.这是-fcommon指定的行为,是大多数目标上GCC的默认行为.另一方面,ISO C不要求这种行为,并且在某些目标上可能会对变量引用带来速度或代码大小的损失.-fno-common选项指定编译器应将未初始化的全局变量放在目标文件的数据部分中,而不是将它们生成为公共块.这样做的结果是,如果extern在两个不同的编译中声明(没有)相同的变量,则在链接它们时会出现多重定义错误.在这种情况下,您必须使用-fcommon进行编译.使用-fno-common进行编译对于提供更好性能的目标非常有用,或者如果您希望验证程序是否可以在其他始终以这种方式处理未初始化变量声明的系统上运行.


我不知道在C标准中有任何提及"一个定义规则"的措辞,但沿着这条线,您可以查看附件§J.5.11,多个外部定义,

对象的标识符可能有多个外部定义,无论是否明确使用关键字extern; 如果定义不一致,或者初始化多个,则行为未定义.