所以只是为了好玩,我有这段代码:
#include <stdio.h>
main()
{
int i;
int a;
i = 17;
//scanf("%d", &i);
a = (i+=5) * (i-=3);
printf("a is %d, i is %d\n", a, i);
}
在C规范中,它表示操作数评估的顺序是未定义,所以我期望看到22 * 19或19 * 14.但是,结果是19 * 19:< / p>
~ $ gcc a.c
~ $ ./a.out
a is 361, i is 19
我想到了这一点,我能想出的唯一解释是编译器做了“延迟”#39;评估(i+=5)
的值,它认为(i+=5)
的值只是i的值。同样适用于(i-=3)
。
但是,如果我取消注释scanf()
:
#include <stdio.h>
main()
{
int i;
int a;
i = 17;
scanf("%d", &i);
a = (i+=5) * (i-=3);
printf("a is %d, i is %d\n", a, i);
}
现在我在提示符下输入17:
~ $ gcc a.c
~ $ ./a.out
17
a is 418, i is 19
为什么它表现出不同的行为?
答案 0 :(得分:5)
未定义的行为。 C标准表示不允许在两个序列点之间多次修改同一个对象(在这种情况下为i
)(在这种情况下,语句之前和之后的分号)。
未定义的行为意味着任何都可能发生。它似乎可以正常工作。它可以给出错误的答案。它可能会使您的流程崩溃。它可以擦除你的硬盘。或者它甚至可以让您的CPU着火。根据语言标准,这些都是允许的行为。
答案 1 :(得分:3)
可能主要区别在于,在第一种情况下, i 可以在整个生命周期内进行预测,因此优化器会预先计算它并用常量值替换变量。
在第二个示例中,scanf无法进行优化。编译器无法事先知道 i 的值是什么,并且符合您的预期,这是标准未定义的。