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
,但仅在循环内可见。
我在写代码时,不小心把 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
,但仅在循环内可见。