1

可能重复:
谁能解释这些未定义的行为(i = i++ + ++i,i = i++ 等……)

我对&& ++ 和 *****的运算符首选项感到困惑

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。有人可以解释一下这种现象吗?

4

7 回答 7

7

y = ++i * ++i;和类似的子句调用未定义的行为,因为它们在两个序列点之间多次修改变量。从字面上看,你可以期待任何事情发生。

n = ++k && ++k;实际上不是 UB,因为该&&运算符是一个逻辑 AND 运算符,并且它是使用短路计算的 - 所以该表达式中有一个序列点,但另一个仍然是错误的。

于 2012-11-15T06:54:12.313 回答
4

他们在这里是不同的。

首先,++i*++i是未定义的行为。有两个副作用,并且没有序列点来拆分它们。

++k&&++k是短路。因为++k是 0。表达式应该是 0。不需要计算第二个++k。重要的&&是序列点。

于 2012-11-15T06:54:43.583 回答
3

运算符的优先级并不决定这些运算符的计算顺序。评估顺序未指定。

优先级规则仅声明 thaty=++i*++i;被解释为y=(++i)*(++i);n=++k&&++k;as n=(++k)&&(++k);,但除此之外,允许编译器以任何顺序实际执行它们。

这条规则有一些例外;例如,标准要求逻辑和运算符 ( &&) 短路;所以这样一个表达式的左边必须在右边之前计算。

例如,考虑表达式a = b+++c。优先规则要求将此表达式解释为a = (b++) + c; 但是编译器可以自由地按照以下任何顺序执行它:

  • 将 b 加一并将旧值存储在临时值中,然后将 c 和临时值相加,然后将结果存储在 a
  • 将 b 和 c 的值相加,然后将结果存储在 a 中,然后递增 b
  • 将 b 和 c 的值相加并将它们存储在临时变量中,然后递增 b 的值,然后将临时变量分配给 a
于 2012-11-15T06:55:04.307 回答
2

这是undefined behaviour在两个序列点之间两次更改变量的值。

y=++i*++i; 在这里,您在两个序列点之间修改 i 两次。

对于序列点,请阅读此链接

n=++k&&++k;但这是定义明确的行为,因为&&它是一个序列点。在这里你得到n == 0因为逻辑短路&&

于 2012-11-15T06:54:23.743 回答
2

优先级在这里无关紧要。

在第一种情况下:++i * ++i,您有未定义的行为,因为您修改i了两次而没有中间的序列点。

在第二种情况下,您有一个&&,它定义了一个序列点,因此您已经定义了行为。具体来说,使用&&,评估左操作数,然后当且仅当它产生非零值时,评估右操作数。结果是and两个结果的逻辑。在您的情况下,k开始为-1,因此当++k评估左侧的 时,结果为 0。由于它为 0,因此根本不评估右侧操作数。

于 2012-11-15T06:55:20.377 回答
0

根据我的理解,将会发生的事情是这样的:

(++k)    && (++k)    -->  ans1 && ans2
-1 -> 0      0 -> 1        0   &&  1   = 0
                              ^ The rest will not be calculated. 

所以首先评估 ++k 但仍然会导致对第一个 ++k 的单独答案(因为相同运算符的从左到右顺序)

因此答案将是 0。

于 2012-11-15T06:55:05.080 回答
0
y=++i*++i;

这是未定义的行为(语言标准不保证变量的输出每次都相同)。

n=++k&&++k;

由于&&是短路运算符,如果结果可以由第一个操作数本身确定,它将不会操作第二个操作数。由于第一个操作数变为0结果为假,即0

于 2012-11-15T06:55:37.870 回答