C++中未初始化的变量行为

omi*_*idh 11 c++ initialization undefined-behavior

我检查过自己,我写了一个这样的程序

int main() {
 int i;
 cout << i;
 return 0;
}
Run Code Online (Sandbox Code Playgroud)

我运行了几次程序,结果一直都是一样的,零.我在C中尝试过,结果是一样的.

但我的教科书说

如果不初始化在函数内定义的变量,则变量值保持未定义.这意味着该元素将采用先前驻留在内存中该位置的任何值.

当程序总是为变量分配空闲内存位置时,这怎么可能?怎么可能是零以外的东西(我假设默认的空闲内存值为零)?

emp*_*nth 13

当程序总是为变量分配空闲内存位置时,这怎么可能?它怎么可能是零而不是零?

我们来看一个示例实际实现.

假设它利用堆栈来保存局部变量.

void
foo(void)
{
        int foo_var = 42;
}

void
bar(void)
{
        int bar_var;
        printf("%d\n", bar_var);
}

int
main(void)
{
        bar();
        foo();
        bar();
}
Run Code Online (Sandbox Code Playgroud)

上面完全破解的代码说明了这一点.在我们调用foo之后,堆栈中放置foo_var的某个位置设置为42.当我们调用bar时,bar_var占据该确切位置.实际上,执行代码会导致打印0和42,表明除非已初始化,否则无法依赖bar_var值.

现在应该清楚,需要局部变量初始化.但主要可能是例外吗?是否有任何可以与堆栈一起玩,结果给我们一个非零值?

是.main不是程序中执行的第一个函数.事实上,设置一切都需要大量的工作.任何这项工作都可以使用堆栈并在其上留下一些非零.您不仅可以在不同的操作系统上获得相同的价值,而且您现在正在使用的系统上可能会突然发生变化.有兴趣的人可以谷歌搜索"动态链接器".

最后,C语言标准甚至没有术语堆栈.拥有局部变量的"位置"留给编译器.它甚至可以从给定寄存器中发生的任何事情中得到随机废话.它真的可以是任何东西.事实上,如果触发了未定义的行为,编译器可以自由地做任何感觉.


Lig*_*ica 9

如果未初始化在函数内定义的变量,则变量值保持未定义.

这一点是真的.

这意味着该元素具有以前驻留在内存中该位置的任何值.

这个位不是.

有时在实践中会发生这种情况,并且您应该意识到,对于任何给定的程序运行,获得零不为零完全符合此理论.

从理论上讲,如果需要,您的编译器实际上可以为该整数分配一个随机的初始值,因此尝试对此进行合理化是完全没有意义的.但是让我们继续,好像我们假设"元素具有以前驻留在内存中那个位置的任何值"......

它怎么可能是零而不是零(我假设默认的空闲内存值为零)?

好吧,这就是你假设的情况.:)


gsa*_*ras 5

此代码调用未定义行为(UB),因为该变量是未初始化的。

当使用警告标志时,编译器应该发出警告,例如-Wall

warning: 'i' is used uninitialized in this function [-Wuninitialized]
  cout << i;
          ^
Run Code Online (Sandbox Code Playgroud)

碰巧的是,在这次运行中,在您的系统上,它的值为 0。这意味着分配给该变量的垃圾值恰好为 0,因为那里的内存剩余表明如此。

但请注意,内核零出现的频率相对较高。这意味着我的系统输出为零是很常见的,但它不能得到保证,也不应该被视为承诺。

  • 我喜欢你提到像“-Wall”这样的编译器标志 (2认同)