为什么在C语言中不能在函数外给全局变量赋值?

7
假设我有一个全局变量,并且我想将另一个变量分配给它。我发现你可以在函数内部将另一个值分配给全局变量:
int i = 8;

int main(void)
{
  i = 9;     /* Modifies i */
  return 0;
}

然而,在函数外部分配全局变量是行不通的!
int i = 8;

i = 9;  /* Compiler error */

int main(void)
{
  return 0;
}

我收到了以下错误信息:

warning: data definition has no type or storage class
warning: type defaults to 'int' in declaration of 'i'
  error: redefinition of 'i'
note: previous definition of 'i' was here
int i = 8;
    ^

为什么会发生这种情况?

2
当它在函数之外时,你会期望它何时执行? - DeiDei
8
函数外只能有定义和声明,不能有一般语句。这是语言规定的方式。 - Some programmer dude
这不是一个适合在SO上提问的好问题。唯一合理的答案是“因为语言设计就是这样”,而询问为什么会这样设计并不具有建设性;它从来就是这样,也不会改变这个问题。在古老的标准中,你可能能够在文件作用域写i = 9;,它会隐式地成为类型int,但是GCC 8.1.0在-std=c90下警告data definition has no type or storage class,无论是否使用-pedantic - Jonathan Leffler
你有没有考虑过更有效的 int i = 9;,而不是 int i = 8; i = 9;?代码执行从 main() 开始。 - Weather Vane
@DeiDei 这实际上是一个有效的观点。 - Galaxy
1个回答

11

这是一个全局变量的定义,可以选择性地将其初始化为特定的值:

int i = 8;
请注意,这并不是会被执行的代码,该变量仅被设置为最初包含8。要么将其视为“魔法”(对于许多标准未定义的东西,这是一个有用的模型),要么将其看作在任何代码被执行之前将带有值的表复制到内存位置中。
这是一段没有“框架”的代码。 (或者你打算这样做。编译器持有其他观点,请参见下文。)
i = 9;

它没有被包含在任何函数中。不清楚何时应该执行它。这就是编译器不喜欢的原因。
在 C 语言中,所有的代码都必须位于函数内部,并且只有在调用该函数时才会执行,例如从 main() 函数中调用。

其他语言,主要是那些通过解释执行“脚本”(而不是将代码转化为可执行文件,例如通过编译器)的语言,允许在任何地方编写代码。但 C 语言不同。

编译器对此有不同的看法:

i = 9;
  • 它不在一个函数内,所以它不能被编译为代码
  • 这看起来像一个变量定义,如果你是想定义一个整型int类型,那就默认使用吧
  • 但是仅依赖默认值并不是一个好主意,因此需要警告缺少类型声明以及默认值的使用
  • 另外,如果它确实是一个定义,那么这将是对变量i的第二次定义,这真的很错误,因此需要显示错误信息并停止编译
  • 仅仅作为帮助,提到第一次定义变量i的地方

这就是如何阅读您引用的编译器输出。


不仅“依赖默认值”不好,而且这种形式在C89中甚至都没有得到支持,GCC现在编译时使用gnu11模式,其中隐式int早已消失。 - Antti Haapala -- Слава Україні
@AnttiHaapala 我同意将其视为错误。OP的编译器(无论是什么)明确表示“警告”。如果双重定义不存在,它是否能够编译将是有趣的事情。 - Yunnosch

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接