【问题标题】:Why local int variables inside `main` function will be initialized automatically?为什么`main`函数中的局部int变量会自动初始化?
【发布时间】:2020-10-16 16:15:42
【问题描述】:

我是 C++ 新手,在学习 C++ 时遇到了这个问题。

这里是代码

#include <iostream>
using namespace std;

void another_func() {
    int a;
    cout << a << endl;
}

int main() {
    int a;
    cout << a << endl;
    another_func();
}

我正在使用g++ (GCC) 10.1.0,我发现每次运行代码时,main 函数中的a 将被初始化为0,而another_func 中的a 将是随机数。如下,

➤  g++ test.cpp && ./a.out
a in main: 0
a in another_func: 32612

据我所知,局部变量存储在堆栈中,它们没有自动初始化机制。所以another_func 中的a 是预期的。但是,谁能告诉我为什么main函数中的a被初始化为0

提前致谢!

【问题讨论】:

  • 其中一些可能取决于您使用的编译器标志。您应该在问题中指定这些内容。
  • 如果算术类型没有显式初始化,它可能是无符号、负数或零,并且为零,并不意味着它具有特定的行为。
  • So the a in another_func is expected 注释掉main 中的cout 行并再次运行。您很可能会得到另一个 a 的不同值,甚至可能是 0
  • 这称为未定义行为,它是C++(和C)的一部分。对于某些程序,它们违反了语言标准中的规则,但编译器不需要报告诊断,也不需要做任何明智的事情。在许多情况下,您看到的行为是编译器仅对遵循规则的程序实施正确行为的意外结果

标签: c++ variables main


【解决方案1】:

tl;dr:你不能读取未初始化的值。

as 都没有初始化为任何东西。这意味着它们有一个不确定的值,可以是包括 0 在内的任何值。任何推理都必须停止,因为读取未初始化的值会调用未定义的行为 (UB)。

UB 意味着任何事情都可能发生。您的程序无效,您不再有任何保证。你不被允许阅读a,所以推理为什么你可能会在特定情况下阅读特定值是没有用的。

这就是 C++ 语言的观点。对于编写 C++ 程序,这通常是您需要自己采用的观点。当然,这涉及到一个编译器。更具体地说,具有特定配置的特定版本中的特定编译器为特定平台编译这段确切的代码。包括您可以对您看到特定结果的原因进行一些调查的所有内容。如果您对编译器的工作方式感兴趣,那么这是一件很有用的事情。但它很少有助于编写程序。更改编译器标志或使用稍微不同的代码,结果可能会有所不同。

【讨论】:

    【解决方案2】:

    未初始化并不意味着非零,它可以有任何值。在许多操作系统上,新分配的内存页面都充满了0,因此在非调试代码中,未初始化的值通常也是0

    您的程序的行为未定义,但可能发生的情况是main 中的a 是堆栈的第一次使用,或者您很幸运,在main 之前运行的初始化代码离开了该区域堆栈的0

    cout 的调用将写入堆栈,因此当您执行another_func 时,堆栈内存将不再是0

    【讨论】:

      【解决方案3】:

      标准不要求局部变量的默认零值,但一些编译器可能会进行零初始化

      只有global 变量和static 成员必须初始化为零,除非另有明确初始化。

      【讨论】:

      • 这里的“一些编译器”部分真正的意思是“不要指望它”。
      猜你喜欢
      • 2011-12-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-29
      • 1970-01-01
      • 2011-12-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多