0

我使用 C 语言,代码如下:

#include <stdio.h>

int main(int argc, char const *argv[])
{
    int num1=0;

    int res = ++num1 && num1++;

    printf("%d\t%d\n",num1,res);    
}

在上面的代码中,我得到的输出为2 1. 我认为输出应该是2 0.

如有错误请指正,为解决此语句,由于优先级最高,首先执行 num1++(0),然后执行 ++num1(2),最后执行 &&,因为它具有最低优先级。

请评论此语句是如何执行的。

在一些教程中,我发现后缀 ++ 和前缀 ++ 具有相同的优先级,但如果这是真的,那么根据关联规则再次 num1++ 应该首先执行(从右到左),这应该再次导致答案为2 0.

4

3 回答 3

3

在用作初始化器的表达式中

 int res = ++num1 && num1++;

运算符有一个序列点&&

来自 C 标准(6.5.13 逻辑与运算符)

3 如果 && 运算符的两个操作数比较不等于 0,则 && 运算符将产生 1;否则,它产生 0。结果具有 int 类型。

4 与按位二进制 & 运算符不同,&& 运算符保证从左到右的求值;如果计算第二个操作数,则在第一个和第二个操作数的计算之间存在一个序列点。如果第一个操作数比较等于 0,则不计算第二个操作数。

首先计算运算符的左操作数,结果num1将等于 1,因为一元(前缀)增量运算符。由于子表达式不等于 0,则计算第二个操作数。它的值是递增之前的值,即 1。由于第二个操作数也不等于 0,因此整个表达式被评估为逻辑真,其值为 1(参见 C 标准的第一个引号)。

该值 1 分配给变量res,而num1后缀增量后的变量将等于 2。

因此,在此声明之后,您将拥有res等于1num1等于2

于 2020-12-18T12:06:12.567 回答
1

这里有很多误解。首先,运算符优先级说明了解析的顺序,而不是执行的顺序。有两个相关但不同的术语,运算符优先级和评估顺序。
请参阅运算符优先级和评估顺序之间有什么区别?.

一旦你了解了求值的顺序,&&操作符就会特别带有明确定义的顺序,而 C 操作符通常不是这种情况。它保证了从左到右的评估顺序。C17 6.5.14/4:

不像按位 | 运算符,|| 运算符保证从左到右的评估;如果计算第二个操作数,则在第一个和第二个操作数的计算之间存在一个序列点。如果第一个操作数比较不等于 0,则不计算第二个操作数。

通常,您无法将 ++ 运算符与其他运算符混合使用,但上述 && 规则使得在这种特定情况下成为可能。

请参阅为什么我们不能将 i++ 之类的增量运算符与其他运算符混合使用?它解释了排序/序列点。


在一些教程中,我发现后缀 ++ 和前缀 ++ 具有相同的优先级,

他们没有,前缀 ++ 优先于后缀(和其他一元运算符)。所以关联性不适用。

于 2020-12-18T12:26:08.643 回答
0

如有错误请指正,为解决此语句,由于优先级最高,首先执行 num1++(0),然后执行 ++num1(2),最后执行 &&,因为它具有最低优先级。

优先级仅控制哪些运算符与哪些操作数分组 - 它不影响计算表达式的顺序。

, &&, ||,?:和逗号运算符都强制从左到右求值 - 左操作数在右操作数之前被完全求值(并应用任何副作用)。 &&并且||两者都短路- 对于&&,只有当左操作数非零时,才会评估右操作数。

一元(前缀)++运算符产生操作数的当前值加 1,因此结果++num11。作为副作用, in 的值num1会增加。由于这个结果是非零的,num1++所以也被评估。后缀++运算符产生操作数的当前值,因此结果num1++1。作为副作用, in 的值num1会增加。

如果两个操作数都不为零,则&&表达式的结果是,否则。10

大致相当于

tmp = num1 + 1;
num1 = num1 + 1;

res = 0;
if ( tmp != 0 )
{
  if ( num1 != 0 )
  {
    res = 1;
  }
}
num1 = num1 + 1;

所以结果是,最后存储的值++num1 && num1++是。1num12

在一些教程中,我发现后缀 ++ 和前缀 ++ 具有相同的优先级,

这是非常错误的,您应该立即停止使用这些教程。后缀运算符比一元运算符具有更高的优先级 -*a++被解析为*(a++)++a[i]被解析为++(a[i])等。表达式 like++i++将被解析为++(i++),但您不能在 C 中编写这样的表达式 - 结果i++不是左值,也不能是像这样的一元的操作数++

于 2020-12-18T15:50:03.287 回答