为什么这个程序没有错误?

— ac —-

int i; // external definition 

—- main.c ——

 int i=0; // external definition int main(void) { i=0; } 

在这两个文件中, i是每个翻译单元中的外部定义,并且i在表达式中使用。 这应该违反:

如果在表达式中使用通过外部链接声明的标识符(而不是作为sizeof运算符的操作数的一部分,其结果是整数常量),则整个程序中的某个地方应该只有一个标识符的外部定义; 否则,不得超过一个.140)

这种非标准行为是许多C编译器中实现的常见扩展

这个问题在Rationale到C99标准中得到了相当广泛的讨论(见第32-34页)。 并且,根据该文档,这套定义在Relaxed Ref / Def模型下是合法的,通常在UNIX OS的C89之前的C编译器中实现。 这就是它受欢迎的原因,这就是为什么我们经常看到它作为扩展实现的原因。 它应该简化对遗留代码的支持。

然而,标准C定义模型是不同的:它是Strict Ref / Def模型初始化模型的组合 。 标准C不允许这样做。

PS虽然aci定义确实是一个暂定的定义 ,但它与该问题无关。 在包含翻译单元结束时,某些对象的所有暂定定义结合并产生对象的外部定义 。 他们的“暂定”性质在模块间层面上并不明显。 暂定定义不允许在不同的翻译单元中创建同一对象的多个定义。