为什么在下面的 C 代码中多次定义变量没有错误?

Why is there no error for a multiple definition of variable in the below C code?

我有两个 2 个文件:

a.c:

#include <stdio.h>

extern int i = 5;

int main(){
    prnt();
}

b.c:

#include <stdio.h>

int i;

void prnt(){
    printf("%d",i);
}

程序在使用 gcc a.c b.c 链接在一起时编译。获得的输出是5。 gcc 编译器不应该给出错误说 multiple definiton of i 因为在 a.c 中,变量 i 是 declareddefined 并且在 b.c 中,已知语句 int i; 隐式定义了值 0 与隐藏的 extern?

答案是"declaration can be done any number of times whereas definition can be done only one time"

为了清楚起见,只要在变量前使用 "extern" 关键字,就意味着该变量刚刚被声明。

外部 int i = 5; -> 这只是声明了一个变量

int i; ---> 定义和声明

这个问题的答案是:

  • 声明可以多次但定义只能一次。
  • 如果仅声明了一个变量,并且还为该声明提供了一个初始化程序,那么将为该变量分配内存,即该变量将被视为已定义。 所以 extern int i = 5;它声明并为变量分配内存 现在我们可以声明 i 变量 n 次了。

首先,为了避免混淆,extern int i = 5;int i = 5;完全相同。是因为C11 6.9.2/1的定义:

If the declaration of an identifier for an object has file scope and an initializer, the declaration is an external definition for the identifier.

(注意这里的 "external definition" 表示文件范围内的定义——不要与 "external linkage" 混淆)。

int i;称为暂定;在这种情况下,它的行为与 int i = 0; 相同(由 6.9.2/2 定义),确认它是一个定义。由于 6.2.2/5,它具有外部链接:

If the declaration of an identifier for an object has file scope and no storage-class specifier, its linkage is external.

所以这两个定义都定义了 i 与外部链接。 C 标准的第 6.2.2/2 节说:

[...] each declaration of a particular identifier with external linkage denotes the same object or function.

所以这两个i表示同一个对象。

从 6.9/5 开始:

If an identifier declared with external linkage is used in an expression (other than as part of the operand of a sizeof or _Alignof operator whose result is an integer constant), somewhere in the entire program there shall be exactly one external definition for the identifier

由于您为 i 提供了两个定义,您的程序违反了此规则,导致未定义的行为,无需诊断。


违反规则是未定义行为的参考是4/2:

If a ‘‘shall’’ or ‘‘shall not’’ requirement that appears outside of a constraint or runtime-constraint is violated, the behavior is undefined.

6.9/5 中引用的部分是 "Semantic:",而不是 "Constraint:",因此它被视为出现在约束之外。