C语言中的运算符优先级

3

我不太理解这个表达:

(x + y - 1) / y * y

运算符优先级如下(根据我的理解和K&R2,2.12表格2.1):
1)首先计算括号中的内容:首先是(x+y),然后是(x+y)-1。
2)'*'运算符的优先级高于'/',所以应该先计算它,但似乎先计算了(y*y),然后将(x+y-1)的结果除以这个积(y*y)。我不太明白。
3)我曾听说通常采用这种形式进行四舍五入:
(x + y - 1) / y * y

这是正确的吗?非常感谢您的帮助!


1
+1 对你的推理过程进行良好的解释,并询问哪里出了问题。这就是一个好的新手问题应该看起来像什么。 - R.. GitHub STOP HELPING ICE
6个回答

6

一元运算符*的优先级高于/,但这是用于指针解引用。

乘法*和除法/具有相同的从左到右优先级。


啊,关于间接(解引用)操作符你发现得不错。这表明相同符号有不同用法(因此造成了困惑)。 - Jeff Mercado

5
不,*/具有相同的优先级(称为“precedence”,而非“priority”)。
(x + y - 1) / y * y

将会是

( ( (x+y) - 1 ) / y ) * y

操作树将是:
           *
          / \
         /   y
        ÷
       / \
      /   y
     -
    / \
   /   1
  +
 / \
x   y

4

如前所述,"*"和"/"具有相同的优先级,因此它们从左到右进行计算。完全消除歧义的表达式为:

( ( ( (x + y) - 1) / y) * y)

2

1)正确

2)不, "/" 和 "*" 具有相同的优先级。因此它们将从左到右执行。

3)我不明白你的“round up”的意思。但是例如:

当 y = 2,x = 2 时

(x + y -1) / y * y = (2 + 2 - 1) / 2 * 2 = (3 / 2) * 2 = 1 * 2 = 2

3 / 2 = 1,因为这是整数除法。


1
“*” 运算符的优先级高于 “/”。
不正确。乘号(*)和除号(/)具有相等的优先级,并且是从左到右结合的。
在计算括号表达式后,我们得到:
(x + y - 1) / y * y = z / y * y      // where z = x + y -1

                    = (z / y) * y    // because of associativity.

0

我可能错了,但据我回忆,'/'和'*'的优先级相同。所以结果应该是(x+y+1)。

如果你想要结果为(x+y+1)/(y*y),也许你应该说出来。

无论如何,消除歧义从来不会花费太多。

至于使用((x+y-1)/y)*y向上或向下舍入,这是一个可疑且不太可移植的做法。原因有几个:1/你必须知道或记住y是某种int类型,2/x也必须是某种int类型,3/结果可能因编译器而异。


不同类型的值确实会产生不同的结果,但为什么它可能因编译器而异呢?我认为在符合规范的实现中,结果是非常明确定义的(除了浮点舍入误差的小例外)。 - ysap
首先,int类型的大小(字节数)并不总是相同的。因此,你可能会在不同的位置进行包装或溢出,这取决于你的数字有多大。另外,并非每个C编译器都符合ANSI标准。 - asoundmove
那是一个有效的参数。然而,在第二个评论中,我提到了我的评论中的兼容实现。 - ysap
@ysap - 的确如此,你可能99.9%的时间都是正确的;-) - asoundmove

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接