我对&& ++ 和 *****的运算符首选项感到困惑
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。有人可以解释一下这种现象吗?
我对&& ++ 和 *****的运算符首选项感到困惑
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。有人可以解释一下这种现象吗?
y = ++i * ++i;和类似的子句调用未定义的行为,因为它们在两个序列点之间多次修改变量。从字面上看,你可以期待任何事情发生。
n = ++k && ++k;实际上不是 UB,因为该&&运算符是一个逻辑 AND 运算符,并且它是使用短路计算的 - 所以该表达式中有一个序列点,但另一个仍然是错误的。
他们在这里是不同的。
首先,++i*++i是未定义的行为。有两个副作用,并且没有序列点来拆分它们。
二++k&&++k是短路。因为++k是 0。表达式应该是 0。不需要计算第二个++k。重要的&&是序列点。
运算符的优先级并不决定这些运算符的计算顺序。评估顺序未指定。
优先级规则仅声明 thaty=++i*++i;被解释为y=(++i)*(++i);和n=++k&&++k;as n=(++k)&&(++k);,但除此之外,允许编译器以任何顺序实际执行它们。
这条规则有一些例外;例如,标准要求逻辑和运算符 ( &&) 短路;所以这样一个表达式的左边必须在右边之前计算。
例如,考虑表达式a = b+++c。优先规则要求将此表达式解释为a = (b++) + c; 但是编译器可以自由地按照以下任何顺序执行它:
这是undefined behaviour在两个序列点之间两次更改变量的值。
y=++i*++i;
在这里,您在两个序列点之间修改 i 两次。
对于序列点,请阅读此链接
n=++k&&++k;但这是定义明确的行为,因为&&它是一个序列点。在这里你得到n == 0因为逻辑短路&&
优先级在这里无关紧要。
在第一种情况下:++i * ++i,您有未定义的行为,因为您修改i了两次而没有中间的序列点。
在第二种情况下,您有一个&&,它定义了一个序列点,因此您已经定义了行为。具体来说,使用&&,评估左操作数,然后当且仅当它产生非零值时,评估右操作数。结果是and两个结果的逻辑。在您的情况下,k开始为-1,因此当++k评估左侧的 时,结果为 0。由于它为 0,因此根本不评估右侧操作数。
根据我的理解,将会发生的事情是这样的:
(++k) && (++k) --> ans1 && ans2
-1 -> 0 0 -> 1 0 && 1 = 0
^ The rest will not be calculated.
所以首先评估 ++k 但仍然会导致对第一个 ++k 的单独答案(因为相同运算符的从左到右顺序)
因此答案将是 0。
y=++i*++i;
这是未定义的行为(语言标准不保证变量的输出每次都相同)。
n=++k&&++k;
由于&&是短路运算符,如果结果可以由第一个操作数本身确定,它将不会操作第二个操作数。由于第一个操作数变为0结果为假,即0