运算符优先级

时间:2011-03-03 09:44:14

标签: c# java python operator-keyword 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

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

Java Python 的情况也是如此吗? 感谢

4 个答案:

答案 0 :(得分:2)

在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>

答案 1 :(得分:2)

C#从左到右评估作业的各边。

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

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

如果没有这样做那么

B.Next = (B = null)

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

答案 2 :(得分:2)

此行为不是运算符优先级的结果,而是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-orfix + ++运算符)。

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

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

e1 op1 e2 op2 e3

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

((e1 op1 e2) op2 e3)

或者是否意味着

(e1 op1 (e2 op2 e3))

告诉您评估e1e2e3的顺序。

答案 3 :(得分:1)

为了完整起见,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的内容相同。