繁体   English   中英

运算符优先级

[英]Operator precedence

考虑一下这个C#类:

class Node
{
    public Node Next;
}

并考虑这两种情况:

        Node A = new Node();
        Node B = A;
        B=(B.Next = new Node());

        Node A = new Node();
        Node B = A;
        B.Next = (B=new Node());

为什么他们会产生相同的结果!?
(A)->(B)->Null

我认为第二种情况会产生一个指向自身的节点,因为运算符优先...

JavaPython也是如此吗? 谢谢

在Python中,您不能以您的方式对分配进行分组。 极端RHS值被分配给左侧的所有标识符。

>>> a = (b=42)
  File "<stdin>", line 1
    a = (b=42)
          ^
SyntaxError: invalid syntax
>>> a = b = 42

>>> print a,b
42 42
>>> 

与您的问题类似

>>> class Node():
...     def __init__(self):
...             self.next = self
... 
>>> n = Node()
>>> n = n.next = Node()
>>> n
<__main__.Node instance at 0x7f07c98eb200>
>>> n.next = n = Node()
>>> n
<__main__.Node instance at 0x7f07c98eb290>

C#从左到右评估赋值的各边。

所以在你的第二种情况下,它在评估RHS之前在最后一行的赋值中“评估”LHS(B.Next),并在A中得到对Next的引用。

无论您在RHS上做什么,都会被分配到此。 所以在RHS上改变B为时已晚。

如果它没有这样做那么

B.Next = (B = null)

将是一个空引用异常,它不会是你期望的那样吗?

此行为不是运算符优先级的结果,而是Java,Python和C#中定义表达式求值顺序的规则的结果。 具体来说,在Java,Python和C#中,表达式从左到右进行计算。 例如,在C和C ++中,这是不正确的,其中您编写的结果将是未定义的。

您可能熟悉这个C拼图:

int i = 1;
printf("%d, %d\n", i++, ++i); // what is printed?

在C中,结果未定义。 它可能是1, 3 ,它可能是2, 2甚至是其他东西。 在Java C#和Python中,结果总是1, 3 (当然除了Python没有pre或postfix ++运算符)。

运算符优先级是一个单独的问题。 它定义了解析树,而不是评估顺序。

假设您使用二进制中缀运算符op1op2的新语言。 并说你有以下代码:

e1 op1 e2 op2 e3

运算符优先级告诉您这是否意味着

((e1 op1 e2) op2 e3)

或者是否意味着

(e1 op1 (e2 op2 e3))

没有告诉您评估e1e2e3的顺序。

为了完整起见,Java在这里像C#一样工作。

    Node A = new Node();

创建一个新节点(让它命名为Node 1),然后让A指向它。

    Node B = A;

这使B指向同一个节点1。

A ----> [Node 1]---> null
           ↑
B −−−−−−−−−'

这就是现在的情况。 那么,现在复杂的最后一行:

    B.Next = 

这会将节点1的下一个指针(B指向的)更改为......

       (B=new Node());

...一个新节点(让我们称之为节点2),同时放入B变量。

A ----> [Node 1]---> [Node 2]----> null
                         ↑
B −−−−−−−−−−−−−−−−−−−−−−−'

这里有趣的是, B.next在赋值的右侧之前进行求值,因此它与在此处编写A.next的相同。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM