C ++函数和变量范围

时间:2018-02-15 16:38:23

标签: c++ function scope

#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而不是垃圾值呢?

3 个答案:

答案 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,这意味着它可以执行任何操作,可以打印任何内容。它可以格式化您的硬盘驱动器或折叠可观察的宇宙!基本上我不知道这样做的编译器实现,但理论上他们可以!