C 运算符优先级,a++ && b++ || 中的逻辑与一元++c

C operator precedence, logical vs unary in a++ && b++ || ++c

在下面的代码中,

int a = 1, b = 2, c = 3, d;
d = a++ && b++ || c++;
printf("%d\n", c);

输出将是 3,我得到它或评估第一个条件,将其视为 1,然后不关心另一个条件,但在 c 中,一元运算符的优先级高于逻辑运算符,就像在数学中一样

2 * 3 + 3 * 4

我们会先计算乘积再求和来计算上面的表达式,为什么 c 不这样做呢?先求所有的一元运算符,再求逻辑的东西?

请注意优先级求值顺序不是同一个概念。 &&|| 的特殊行为表明 right-hand 端根本不会被评估,如果它不是必须的。优先级告诉你一些关于如果它被评估将如何被评估的事情。

换句话说,优先级有助于描述如何解析表达式。但并没有直接说如何评价。 Precedence 告诉我们,解析您询问的表达式的方法是:

      ||
      / \
     /   \
    &&   c++
   / \
  /   \
a++    b++

但是当我们去评估这个解析树时,&&|| 的 short-circuiting 行为告诉我们,如果 left-hand 端决定结果,我们根本不会站在 right-hand 一边评估任何东西。在这种情况下,由于 a++ && b++ 为真,|| 运算符知道其结果将为 1,因此它根本不会导致 c++ 部分被计算。

这也是为什么像

这样的条件表达式
if(p != NULL && *p != '[=11=]')

if(n == 0 || sum / n == 0)

很安全。第一个不会崩溃,不会尝试访问 *p,在 p 为 NULL 的情况下。如果 n 为 0,则第二个不会除以 0。


很容易对计算的优先级和顺序产生错误的印象。当我们有一个像

这样的表达式时
1 + 2 * 3

我们总是说 "the higher precedence of * over + means that the multiplication happens first" 这样的话。但是如果我们像这样抛出一些函数调用会怎样:

f() + g() * h()

这三个函数中的哪一个会先被调用?事实证明我们不知道。优先级并没有告诉我们这一点。编译器可以安排先调用 f(),即使它的结果是最后需要的。另见 .