可能重复:
Could anyone explain these undefined behaviors (i = i++ + ++i , i = i++, etc…)
我对&& ++和*****
的操作员偏好感到困惑int i=-1,k=-1,y,n;
y=++i*++i;
n=++k&&++k;
printf("%d %d %d %d",i,y,k,n);
输出gcc:1 1 0 0
这里,对于y的情况,最初i增加一次,即i = 0并且i再次增加,即i = 1现在i * i完成,即25 因为++具有比*
在第二种情况下,即使++具有比&&更高的偏好,k也不会增加到1。任何人都可以解释一下这个现象吗?
答案 0 :(得分:7)
y = ++i * ++i;
和类似的子句调用未定义的行为,因为它们在两个序列点之间多次修改变量。从字面上看,你可以期待任何事情发生。
n = ++k && ++k;
实际上不是UB,因为&&
运算符是逻辑AND运算符并且使用短路进行评估 - 所以是的序列点表达,但另一个仍然是错误的。
答案 1 :(得分:4)
他们在这里不同。
首先,++i*++i
是未定义的行为。有两种副作用,没有序列点来分割它们。
其次,++k&&++k
是短路的。由于++k
为0.表达式应为0.无需评估第二个++k
。重要的是&&
是序列点。
答案 2 :(得分:3)
运算符的优先级并不决定评估这些运算符的顺序。评估顺序未指定。
优先规则仅表示y=++i*++i;
被解释为y=(++i)*(++i);
而n=++k&&++k;
被解释为n=(++k)&&(++k);
,但是否则允许编译器以任何顺序实际执行它们。< / p>
这条规则有一些例外;例如,标准要求逻辑和运算符(&&
)短路;所以必须在右侧之前评估这种表达式的左侧。
例如,考虑表达式a = b+++c
。优先规则要求将此表达式解释为a = (b++) + c
;但是编译器可以自由地以下列任何顺序执行:
答案 3 :(得分:2)
这是undefined behaviour
。在两个序列点之间改变变量的值两次。
y=++i*++i;
在这里你要在两个序列点之间修改两次。
对于序列点,请阅读此link
n=++k&&++k;
但这是明确定义的行为,因为&&
是一个序列点。
由于逻辑n == 0
&&
答案 4 :(得分:2)
优先权与此无关。
在第一种情况:++i * ++i
,您有未定义的行为,因为您在没有插入序列点的情况下重新修改i
两次。
在第二种情况下,您有一个&&
,它定义了一个序列点,因此您已定义了行为。具体来说,使用&&
计算左操作数,然后当且仅当它产生非零值时,才会计算右操作数。结果是两个结果的逻辑and
。在您的情况下,k
以-1
开头,因此当评估左侧的++k
时,结果为0.因为它是0,所以右操作数不是&# 39; t得到评估。
答案 5 :(得分:0)
根据我对此的理解,将会发生这样的事情:
(++k) && (++k) --> ans1 && ans2
-1 -> 0 0 -> 1 0 && 1 = 0
^ The rest will not be calculated.
因此首先评估++ k,但仍然会导致对第一个++ k的单独答案(因为在相同的运算符上从左到右)
因此答案为0。
答案 6 :(得分:0)
y=++i*++i;
是未定义的行为(语言标准不保证变量的输出每次都相同)。
n=++k&&++k;
由于&&
是短路运算符,如果结果可以由第一个操作数本身确定,则它不会运行第二个操作数。由于第一个操作数变为0
,因此结果为false,即0