c++ 调用 int 两次

c++ calling int twice

我在写代码时,不小心把 int 放在一个变量前面两次,发现最终产品有些不同。

int main ()
{
    int number = 123456789;
    int step = 0;

    while (number>0)
    {
        cout << number%10 << endl;
        number = number/10;
        step = step+1;
        cout << "step ; " << step << endl;
    }

    return 0;
}

输出为:

9
step ; 1
8
step ; 2
7
step ; 3
6 ...

然而,当我这样称呼它时:

int main ()
{
    int number = 123456789;
    int step = 0;

    while (number>0)
    {
        cout << number%10 << endl;
        number = number/10;
        int step = step+1;
        cout << "step ; " << step << endl;
    }

    return 0;
}

输出突然变成:

9
step ; 11006125
8
step ; 11006126
7
step ; 11006127
6

谁能解释一下区别,以便我下次注意?

C++ 是块作用域的。当您在 while 循环内重新声明 step 时(通过使用 int step 而不仅仅是 step),您从该范围外“隐藏”了 step;虽然外部step(值为0)仍然存在,但不能直接从内部范围读取(一个 pointer/reference 到外部 step 的不同名称可以 read/write 数据,你不能直接通过该名称读取外部 step

外面的step是不可见的,所以int step = step + 1;翻译成“请将已经存储在本地step中的值分配给本地step(在添加 1 之后,它直到那一刻才存在,还没有定义的值)。由于它从中读取的 step 是垃圾,这是未定义的行为,实际上,它得到的是垃圾(在您输入 while 之前恰好留在堆栈中该位置的任何垃圾)。

内部 step 的第二次和后续创建仍然是未定义的行为,但在这种情况下(以及在不涉及循环展开的大多数情况下)编译器选择为它们重用相同的存储作为 inner step 的先前使用(在循环迭代结束时过期)。因此,巧合的是,新的内部step从与过期的内部step相同的内存位置读取,它从那时起正常递增,基于原始垃圾值作为基础。

但再次声明,所有这些都是未定义的行为。庆幸没有得鼻魔,以后只用第一种形态。我会注意到,如果您启用所有警告,任何称职的编译器都应该检测到此错误(整个错误存在于单行范围内);可悲的是,至少 GCC 似乎不值一提,因为 the only thing it detects, even with -Wall -Wextra -Werror -pedantic is that you didn't use the outer step variable. If you used it, or deleted the declaration of the outer step, it compiles with no warnings,所以我猜你只是记住不要根据变量自身的值来初始化变量。

在第二种情况下,您声明了第二个变量,也称为 step,但仅在循环内可见。