为什么 C 和 Java 中的优先级和关联性规则不同?[复制]

Why are the precedence and associativity rules different in C and Java? [duplicate]

提问人:Pardha Saradhi 提问时间:5/17/2022 最后编辑:Jonathan LefflerPardha Saradhi 更新时间:5/17/2022 访问量:117

问:

我发现 C、C++ 和 Java 中的优先级和关联规则是不同的。 请看以下代码片段:

#include<stdio.h>
void main(){
    int k = 5;
    int x = ++k*k--*4;
    printf("%d",x);
}

上面的 C 程序给出的输出为 120

查看以下 Java 代码:

class Main
{
   public static void main(String args[])
   {
      int k = 5;
      int x = ++k*k--*4;
      System.out.println(x);
   }
}

此 Java 代码给出 144 作为输出。 为什么会有这种差异? 我认为 Java 评估策略是正确的,因为它的评估结果为(增量前)6 * 6(递减后)*4 = 144

那么 C 和 C++ 有什么问题呢?C 和 C++ 都给出 120。

Java C++ C 运算符优先级 关联性

评论

7赞 Jonathan Leffler 5/17/2022
未定义的行为是 C(和 C++)的一部分。在这样的语句中递增和递减是 C 中的 UB。C或C++没有任何问题。你对 C 和 Java 必须表现相同的期望是错误的,仅此而已。k
1赞 Silvio Mayolo 5/17/2022
这不是优先级问题。C 和 C++ 有意不指定评估顺序,在特定情况(例如跨短路和 )。||&&
5赞 Taekahn 5/17/2022
“为什么两种不同的语言不同”,因为它们是。
2赞 Jonathan Leffler 5/17/2022
@DawoodibnKareem — 396 在 C 中也有效,-937 也是如此。行为是未定义的,任何结果都是有效的。
2赞 Peter 5/17/2022
就个人而言,我认为 C 和 C++ 在这种特殊情况下有更好的方法(在其他情况下,我认为 Java 做得更好)。使行为未定义有助于阻止编写神秘代码,使代码更难理解,使编写代码的人更难正确,其他人更难理解。更一般地说,C和C++是错误的,而Java在某种程度上是正确的隐含假设简直是无稽之谈 - 它们是不同的语言,具有不同的目的,因此一种技术中的好技术可能是另一种技术中的坏技术。

答:

3赞 dbush 5/17/2022 #1

在 Java 中,可以保证从左到右评估大多数操作数,包括副作用。

C 和 C++ 不做这样的保证。除了 、、(三元运算符)和(逗号运算符)之外,操作数的计算顺序未指定,可能产生的任何副作用也是如此。||&&?:,

在这种情况下:

int x = ++k*k--*4; 

变量被写入多次,而没有中间的序列点。这会触发未定义的行为k

评论

0赞 Peter 5/17/2022
请注意,较新的 C++ 标准(C++11 及更高版本)不再使用术语“序列点”。他们只是说,如果标量对象上的副作用相对于同一对象上的其他副作用是未排序的,那么行为就被定义了。
0赞 Lundin 5/17/2022
@Peter 他们仍然使用术语序列点,只是没有在您引用的 6.5/2 部分中使用。它仍然是 5.1.2.3 中定义的正式术语。SO 上流传着奇怪的谣言,说序列点被完全删除了。