C运算符优先级不起作用

时间:2012-11-15 06:49:00

标签: c

  

可能重复:
  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。任何人都可以解释一下这个现象吗?

7 个答案:

答案 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;但是编译器可以自由地以下列任何顺序执行:

  • 在b中添加一个并将旧值存储在临时值中,然后将c和临时值一起添加,然后将结果存储在
  • 将b和c的值加在一起,然后将结果存储在a中,然后将b
  • 递增
  • 将b和c的值一起添加并存储在临时值中,然后递增b的值,然后将临时值分配给

答案 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