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

Piy*_*ain 1 c gcc extern

我有两个2个文件:

AC:

#include <stdio.h>

extern int i = 5;

int main(){
    prnt();
}
Run Code Online (Sandbox Code Playgroud)

公元前:

#include <stdio.h>

int i;

void prnt(){
    printf("%d",i);
}
Run Code Online (Sandbox Code Playgroud)

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

M.M*_*M.M 5

首先,为避免混淆,extern int i = 5;完全相同int i = 5;.这是一个定义,因为C11 6.9.2/1:

如果对象的标识符声明具有文件范围和初始化程序,则声明是标识符的外部定义.

(注意,"外部定义"在这里表示文件范围的定义 - 不要与"外部链接"混淆).

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

如果对象的标识符声明具有文件范围而没有存储类说明符,则其链接是外部的.

因此,这两个定义都i与外部联系有关.C标准第6.2.2/2节说:

[...]具有外部链接的特定标识符的每个声明表示相同的对象或功能.

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

从6.9/5:

如果在表达式中使用通过外部链接声明的标识符(除了作为sizeof或_Alignof运算符的操作数的一部分,其结果是整数常量),整个程序中的某个地方应该只有一个标识符的外部定义

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


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

如果违反约束或运行时约束之外的''shall''或''shall not''要求,则行为未定义.

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