#include<iostream>
using namespace std;
void fun(int a) {
int x;
cout << x << endl;
x = a;
}
int main() {
fun(12);
fun(1);
return 0;
}
此代码的输出如下:
178293 //garbage value
12
为什么我们得到12
而不是垃圾值呢?
答案 0 :(得分:0)
打印时,您尚未初始化值x
。从未初始化的内存中读取是UB,即,不能保证会发生什么。它可以输出一个随机数,或调用一个不太可能的比特组合,这些比特会做出意想不到的事情。
答案 1 :(得分:0)
为什么我们得到12而不是垃圾值呢?
理论上,x
的价值可能是任何东西。但是,在实践中发生的事情是,fun
两个一个接一个地调用,导致x
的先前值仍然在堆栈帧上。
让我们说堆栈帧的结构如下:
arguments
return value
local variables
在你的情况下,
用于参数的内存等于sizeof(int)
由于返回类型为void
,编译器可能会省略使用任何内存作为返回值
用于局部变量的内存等于sizeof(int)
。
当第一次进行函数调用时,参数部分中的值设置为12.正如您所注意到的,局部变量中的值是垃圾。但是,在从函数返回之前,将局部变量的值设置为12。
第二次创建函数时,参数的值设置为1.局部变量中的值仍然是前一次调用的剩余部分。因此,它仍然是12.如果你第三次调用该函数,你可能会在局部变量中看到值1。
无论如何,这是一个似是而非的解释。再一次,请记住这是未定义的行为。不要指望任何特定的行为。编译器可以决定在使用之前擦除堆栈帧。编译器可以决定在使用后立即擦除堆栈帧。编译器在使用后可以对堆栈帧做任何想做的事情。如果在fun
的调用之间有另一个电话,您很可能会得到完全不同的值。
答案 2 :(得分:0)
读取未初始化的整数是UNDEFINED BEHAVIOR
,这意味着它可以执行任何操作,可以打印任何内容。它可以格式化您的硬盘驱动器或折叠可观察的宇宙!基本上我不知道这样做的编译器实现,但理论上他们可以!