提供此代码:
#include <iostream>
#include <cmath>
using namespace std;
int main() {
int k, x;
while(k > x-3) {
k--;
// cout << "x = " << x << "\n";
}
x++, k--;
int aux = abs(k-x);
cout << aux;
}
当我们运行它时,它总是弹出一个常数x(x = 50),并且整数k和x之间的绝对值始终为5。能否请您解释一下为什么以及它如何工作?
答案 0 :(得分:4)
在约束“ k
大于x
”的情况下,这段代码在这里
while(k > x-3) {
k--;
// cout << "x = " << x << "\n";
}
将k
减少为3
x
。
下一行x++, k++;
将它们都增加1
,但不会改变结果。 k
仍比3
小x
。
k-x
是-3
,而abs(k-x)
是3
,因此为什么程序总是打印3
。当然,假设k
和x
都已初始化,并且k
比x
大。用k
和x
未初始化发布的程序表现出未定义的行为,因此无法保证会发生什么。同样,如阿空加瓜所指出的那样,如果x
小于INT_MIN + 3
,也会导致不确定的行为。
答案 1 :(得分:0)
Matthieu和πάνταῥεῖ是正确的:这是经典的未定义行为。 (将其设为 undefined 而非简单地定义为 unspecified 或实现定义的一个基本原理是,某些体系结构具有未初始化寄存器的标志并且会被捕获。)编译器实际上可以自由地将其编译为空程序:读取未初始化的变量可能会导致任何东西 —而 nothing 是 anything 的子集。未定义行为之后的所有后续代码都被前面的错误“污染”,可以忽略。请注意,不同的体系结构和不同的编译器,甚至可能是不同的C标准库(使用相同的编译器!)可能会得出不同的结果。甚至不同的编译器标记(关于优化或函数调用约定)也可能会更改此不确定的行为。
(此答案的其余部分适用于该问题的版本,其中循环后的行读取x++, k++;
(而不是现在的k--
。)。
但是您遇到了一致的行为,问题是为什么它是一致的。第一个假设是编译器不会简单地生成代码以输出“ 5”(它可以合法地),而是实际上“天真”地生成与C语句相对应的机器代码。我们将按照声明进行推理。
然后,该行为表明x和k所在的存储位置包含立即使k > x -3
为假的值。 (否则,k将递减,直到相差为3,而不是5)。
如果条件为假,变量差将不会改变;从中我们可以得出结论,从x-k == 5
开始它是5。如果省略abs()
,则输出应为-5
。
变量具有这些一致的初始值的原因可能与操作系统或C运行时环境在程序启动时所做的事情有关,例如初始化标准流。尝试使用printf
而不是cout
来查看结果是否更改。
答案 2 :(得分:0)
我真的认为您应该尝试两个任意数字。
例如,假设我们正在使用k= 10 & x=8
。
您的循环如下所示:
While(10>5) 10-1=9
...依此类推,直到K不大于(X-3)。
您将得到k = 5,x是相同的值,8。
在while循环之后,您递减k,然后递增x,因此k = 4和x = 9。
Abs(k-x) = 5
。
如果您需要更多理论上的解释,则循环将使您的两个变量之间的差为3,则X将大于K。 在循环之后,您递减K并递增X,它们之间的差总是5。