C中允许重新声明全局变量?

C中允许重新声明全局变量?,c,variables,storage,global,declaration,C,Variables,Storage,Global,Declaration,为什么C中允许使用此代码 int x; int main() { printf("%d\n", x); return 0; } int x = 2; 它使用-Wall-std=c89和gcc和clang进行编译而不发出警告 我以前认为全局范围内的intx相当于intx=0。我发现自己很惊讶 int x; 这是一份声明 int x = 2; 是一个定义(也是一个声明) 只要声明兼容(相同),就允许重新声明 会有用的。不允许重新定义 int x = 2; int x = 2

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

int x;

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

int x = 2;
它使用
-Wall-std=c89
gcc
clang
进行编译而不发出警告

我以前认为全局范围内的
intx
相当于
intx=0
。我发现自己很惊讶

int x;
这是一份声明

int x = 2;
是一个定义(也是一个声明)

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

会有用的。不允许重新定义

int x = 2;
int x = 2;
不起作用。
不允许在没有声明或没有定义的情况下使用

这是一份声明

int x = 2;
是一个定义(也是一个声明)

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

会有用的。不允许重新定义

int x = 2;
int x = 2;
不起作用。

不允许在没有声明或没有定义的情况下使用int x是一个试探性的定义,其回答与
intx=0类似如果不存在具有初始化的定义

我以前认为全局范围内的
intx
相当于
intx=0

关于“全局”
intx的棘手部分假定它已用0初始化。如果另一个
int x=常数,则初始化为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;

intx是一个试探性的定义,其回答与
intx=0类似如果不存在具有初始化的定义

我以前认为全局范围内的
intx
相当于
intx=0

关于“全局”
intx的棘手部分假定它已用0初始化。如果另一个
int x=常数,则初始化为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;

intx是一个暂定定义。和
intx=2
也是一个声明。@Olaf,是的,但只要有真正的定义,试探性的定义是不相关的。正如名字所说,只要没有其他链接出现,这些名称都是暂定的。带有外部链接的名称应该总是有一个
extern
声明,最好是在头文件中。否则使用内部链接。@JensGustedt:没错。但使用正确的术语总是好的。OP显然想知道
intx本身也是有效的。这“在技术上是正确的”:
intx
是一个声明,并且
intx=2既是一个声明也是一个定义。但是它没有提到
intx
也是一个定义,对于回答这个问题至关重要。
intx是一个暂定定义。和
intx=2
也是一个声明。@Olaf,是的,但只要有真正的定义,试探性的定义是不相关的。正如名字所说,只要没有其他链接出现,这些名称都是暂定的。带有外部链接的名称应该总是有一个
extern
声明,最好是在头文件中。否则使用内部链接。@JensGustedt:没错。但使用正确的术语总是好的。OP显然想知道
intx本身也是有效的。这“在技术上是正确的”:
intx
是一个声明,并且
intx=2既是一个声明也是一个定义。但是它没有提到
intx
也是一个定义,它对回答这个问题至关重要。@pablo1977
x
是一个静态变量@pablo1977
x
是一个静态变量!我认为这并不完全正确。本标准不包括在一个TU中有一个暂定定义,在另一个TU中有一个初始值设定项。这是两个相反的定义,因此导致UB。不过,gcc将此作为一个扩展,但其他编译器可能不会这样做。@JensGustedt也许是这样。我会复习的。我认为这不完全正确。本标准不包括在一个TU中有一个暂定定义,在另一个TU中有一个初始值设定项。这是两个相反的定义,因此导致UB。不过,gcc将此作为一个扩展,但其他编译器可能不会这样做。@JensGustedt也许是这样。我们将进行审查。