【问题标题】:operator precedence in C?C中的运算符优先级?
【发布时间】:2017-12-15 10:15:09
【问题描述】:
int x=12;
int y=7;
int z=19;
int sum;

sum = ++x >= y * 2 || y % 2 && z++ % 2;

我对运算符优先级有点困惑? 编译器将在上述代码中读取的第一个条件是什么? 它是否会首先评估y % 2 && z++ % 2,因为&& 优先于||,或者如果最左边的++x >= y * 2 为真,编译器是否仍会从左到右并短路?即编译器会按照以下方式读取代码吗?

sum = (++x >= y * 2 || y % 2 )&& z++ % 2;

【问题讨论】:

  • 如有疑问,您只需添加() 即可获得所需的订单。如此复杂的代码永远不会有任何实际用途。
  • @BoPersson:很有趣,但我坐在围栏的另一边,而且教条主义。学习您的优先表不会花费很长时间,并且可以使代码更具可读性。
  • @Bathsheba - 是的,知道+* 的顺序很好,但是当它是&& z++ % 2 时就没有多大用处了。
  • @Stannis - 我认为这对考试有用。如果你在我的代码审查中尝试这个,你会得到最后的警告。再一次,你会寻找一份新工作。 :-)
  • @zerkms 关联性只有在两个具有相同优先级的运算符彼此相邻时才会发挥作用。它不适用于此表达式的任何地方。

标签: c operator-precedence


【解决方案1】:

你的表达被归类为

(++x >= (y * 2)) || ((y % 2) && (z++ % 2))

这是分配给sum。这是由 C 的 语法 指定的。

另请注意,如果左侧是 1,则 || 的右侧评估:这意味着在这种情况下 z 不会增加。 p>

  1. 为免生疑问,++xx 值,z++z 值。

  2. 1234563
  3. 调用sum 的结果是一种混淆练习。

【讨论】:

  • 谢谢,是的,我知道|| 的右侧不会在左侧为真时进行评估,但这里真正让我感到困惑的是|| 的左侧是否会评估因为&& 的优先级高于||
  • @StannisBaratheon 大致优先级告诉您可以添加括号的方式以及关联性以及相同优先级表达式的多个运算符中的评估顺序。优先级告诉你a || b && c || d应该读作a || (b&&c) || d,关联性告诉你首先要评估的是a || (b&&c)
  • @Jean-BaptisteYunès 关联性也只告诉您如何添加括号。具体来说,它会告诉您x $ y $ z 是否等同于x $ (y $ z)(如果$ 是右关联运算符)或(x $ y) $ z(如果它是左关联运算符)。这仍然不能告诉您是先计算左操作数还是先计算右操作数。
【解决方案2】:

评估顺序与优先级(或相关性)无关。 && 的优先级高于|| 的事实告诉您a || b && c 等价于a || (b && c)。这并不能告诉您是先评估 a 还是 b && c

||&& 的情况下,标准规定首先评估左操作数(如果左操作数评估为真(在|| 的情况下)或假,则根本不评估右操作数(在&&的情况下)。所以在a || (b && c),我们知道顺序是ab,然后是c(假设所有三个最终都被评估)。

对于其他大部分操作符,标准并没有规定求值顺序,所以比如a + b * c,我们知道它等价于a + (b * c),但不知道a是否被求值在b * c 之前,或者b 是否在c 之前进行评估。

【讨论】:

    【解决方案3】:

    运算符优先级指定如何解析表达式,而不是如何评估它。虽然相关,但评估顺序是不同的!它要么由特定的运算符指定,要么未指定。

    运算符优先级规定表达式等价于:

    sum = ( ((++x) >= (y * 2)) || ((y % 2) && ((z++) % 2)) );
    

    as 运算符的优先顺序如下:

    ++ (postfix)
    ++ (prefix)
    * % (same precedence)
    >=
    &&
    ||
    

    如果您认为sum = ( ((++x) >= (y * 2)) || ((y % 2) && ((z++) % 2)) ); 是一团难以辨认的混乱,那您是对的。然而,它和原来的表达一样糟糕。如果可以避免的话,千万不要像这样在一行上写多个运算符。

    这就是我们使用运算符优先级的情况。它只是将特定的运算符与操作数“粘合”在一起。它没有规定评估的顺序。

    把它想象成数学:在数学表达式(1 + 1 + 1 * 2 + 2 + 2) 中,数学的运算符优先级保证1 * 2 中的12 属于一起,但它不会告诉你以哪个顺序你应该解方程。您可以通过先计算1 + 11 * 22 + 2 来开始解决它。

    在表达式sum = ++x >= y * 2 || y % 2 && z++ % 2 中,只有||&& 指定了求值顺序。特别是这两个运算符有时被非正式地称为具有“短路”评估。

    对于其余的运算符,评估顺序是未指定,这意味着我们无法了解或依赖它。编译器甚至不需要在表达式之间保持一致 - 原因是允许编译器在解析其表达式树时生成尽可能快的代码。

    我们可以知道的唯一一件事是子表达式++xy * 2[result of ++x] >= [result of y * 2] 在@987654337 的右侧之前被评估@。

    反过来,如果|| 的右侧确实被求值,那么y % 2 将在其余子表达式之前求值,因为&& 确实保证了其操作数的求值顺序。

    【讨论】:

      猜你喜欢
      • 2013-02-24
      • 2017-06-02
      • 1970-01-01
      • 2013-02-09
      • 1970-01-01
      • 2021-03-29
      相关资源
      最近更新 更多