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

标签 c gcc extern

我有两个 2 文件:

交流电:

#include <stdio.h>

extern int i = 5;

int main(){
    prnt();
}

公元前:

#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?

最佳答案

首先,为避免混淆,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.

(请注意,此处的“外部定义”是指文件范围内的定义——不要与“外部链接”混淆)。

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 中引用的部分是“语义:”,而不是“约束:”,因此它被视为出现在约束之外。

关于c - 为什么在下面的 C 代码中多次定义变量没有错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32450173/

相关文章:

linux - "Illegal instruction"当运行针对我的 CPU 的 ARM 代码时

c++ - 如何在命名空间中初始化外部变量

c++ - 在两个 cpp 文件的 header 中共享定义的全局变量

c - Make - 无所事事 - 只有文件扩展名

c++ - 遍历迷宫和深度优先搜索

C 字符数组的长度与预期不同

c - fprintf 是否在幕后使用 malloc() ?

c++ - 本地结构通过使用通用模板函数影响不同的翻译单元

c - 将 "falign-functions"编译器标志显式设置为特定值的动机是什么?

c - Extern "C"NULL 函数指针