【问题标题】:Redeclaration of global variables allowed in C?C中允许重新声明全局变量?
【发布时间】:2023-12-18 21:30:01
【问题描述】:

为什么在 C 中允许使用此代码?

int x;

int main() {
    printf("%d\n", x);
    return 0;
}

int x = 2;

使用-Wall -std=c89gccclang 编译时不会出现警告。

我之前认为int x在全局范围内等价于int x = 0。我发现自己很惊讶。

【问题讨论】:

  • @pablo1977 x 一个静态变量!

标签: c variables storage global declaration


【解决方案1】:

int x;,在文件范围内,是一个暂定定义,也由@PSkocik 回答,如果不存在具有初始化的定义,则其行为类似于int x = 0;

我之前认为int x在全局范围内等价于int x = 0

关于“全局”int x; 的棘手部分是假设它被初始化为 0。如果在 any 编译单元中不存在另一个 int x = constant;,它被初始化为 0。

因此建议显式初始化,而不是在对象需要初始化时将默认初始化为 0 位。

// Does an initialization exist, in some file -maybe?
int x;
// Better.  If another file initializes `x`, good to see a compiler/linker error.
int x = 0;

【讨论】:

  • 我认为这并不完全正确。在一个 TU 中有一个暂定定义,在另一个 TU 中有一个带有初始化程序的定义,不在标准中涵盖。这是两个相互矛盾的定义,因此导致了 UB。不过,gcc 将此作为扩展,但其他编译器可能不会。
  • @JensGustedt 也许是这样。将审查。
【解决方案2】:
int x;

是一个声明。

int x = 2;

是一个定义(也是一个声明)。

只要声明兼容(相同),就允许重新声明。

int x;
int x;

会工作。不允许重新定义

int x = 2;
int x = 2;

不会工作。
不允许在其前没有声明或没有定义的情况下使用

【讨论】:

  • int x; 在文件范围内是一个暂定定义。而int x = 2;也是一个声明。
  • @Olaf,是的,但只要有真正的定义,试探性的定义就无关紧要。顾名思义,只要没有其他人出现,这些都是暂定的。
  • 并且具有外部链接的名称应始终具有extern 声明,最好在头文件中。否则使用内部链接。
  • @JensGustedt:没错。但是使用正确的术语总是好的。 OP 显然想知道 int x; 单独也有效,我的评论解释了这一点。
  • 这是“技术上正确的”:int x; 是声明,int x=2; 既是声明又是定义。但是它没有提到int x; 也是一个定义,这对于回答问题至关重要。