Java前缀和一元运算符在一起

时间:2016-02-11 17:50:03

标签: java syntax-error unary-operator prefix-operator

我正在研究Java前缀运算符并遇到了这种行为

i = +--j //does not give an error
i = -++j //does not give an error

i = ---j //gives an error
i = +++j //gives an error

为什么会这样?

3 个答案:

答案 0 :(得分:6)

由于int *new_array(void) { static const int arr[] = { 1, 2, 3, 4, 5 }; int *result = arr; /* or &arr[0] */ return result; /* or "return arr;" */ } +(或+++-)都是左关联的,--被评估为+++j。由于++(+j)只能应用于l值(即变量)而++不是l值(变量),因此会出现编译错误。

您可以使用括号来解决此问题:+j

答案 1 :(得分:2)

编译器使用贪婪的从左到右的标记选择。因此,当它看到+--j时,作为有效令牌的最长序列是+,因为+-不是有效令牌,所以它需要+作为第一个令牌。然后它查看可以识别为令牌的下一个最大的事物,即--j。  结果是+ --j

对于---j,它会将--视为最长的有效令牌,然后-j作为下一个有效令牌,并尝试将它们组合为-- -j,作为@ Mureinik指出,无效。

答案 2 :(得分:1)

在编译器甚至到达知道哪些运算符存在的点之前,它必须解析它们。我可以看到---j的3种可能的解析:

  • - - -j // 3 unary - operators
  • -- -j // predecrement -- followed by unary -
  • - --j // unary - followed by predecrement --

+++j的案例是等效的,其中包含前递增++和一元+

为什么Java将其解释为--后跟-,第二种情况,这是唯一一个在语法上无效的情况?编译器通常是 greedy Section 3.2 of the JLS州:

  

使用以下三个词汇翻译步骤将原始Unicode字符流转换为一系列标记,这些步骤依次应用:

...

  

每个步骤使用最长的翻译,即使结果最终没有制作正确的节目,而另一个词汇翻译。有一个例外:如果词汇翻译发生在类型上下文(§4.11)中,并且输入流有两个或更多连续的>非>后面跟着的字符字符,然后每个>必须将字符转换为数字比较运算符的标记>。

(大胆强调我的)

编译器贪婪地看到两个-个字符并立即将其声明为--令牌,而不考虑接下来的第三个-

这与运算符关联性甚至运算符优先级无关,也与语法分析有关。

正如@Mureinik已经提到的那样,正确放置澄清括号将迫使编译器正确解析它。但它通过将字符分解为不同的标记来实现这一点,而不是通过改变操作的优先级来实现。

表达式-++j不受编译器贪婪的影响; -+不是有效令牌,因此会将其正确解析为令牌-,后跟令牌++,对于表达式+--j也是如此。