简体   繁体   English

运算符优先级

[英]Operator precedence

Consider this C# class: 考虑一下这个C#类:

class Node
{
    public Node Next;
}

And consider these 2 cases: 并考虑这两种情况:

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

and

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

Why do they produce the same results!? 为什么他们会产生相同的结果!?
(A)->(B)->Null

I thought the 2nd case would produce a node pointing to itself because of operator precedence... 我认为第二种情况会产生一个指向自身的节点,因为运算符优先...

Is that the case in Java and Python too? JavaPython也是如此吗? Thanks 谢谢

In Python, you cannot group assignments in the way you have done. 在Python中,您不能以您的方式对分配进行分组。 The extreme RHS value is assigned to all the identifiers towards it's left. 极端RHS值被分配给左侧的所有标识符。

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

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

Similar to your question 与您的问题类似

>>> 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# evaluates the sides of the assignment from left to right. C#从左到右评估赋值的各边。

So in your second case it is 'evaluating' the LHS (B.Next) in the assignment on the last line before it evaluates the RHS, and arriving at the reference to Next in A. 所以在你的第二种情况下,它在评估RHS之前在最后一行的赋值中“评估”LHS(B.Next),并在A中得到对Next的引用。

Whatever you do on the RHS is assigned to this. 无论您在RHS上做什么,都会被分配到此。 So changing B on the RHS is too late. 所以在RHS上改变B为时已晚。

If it didn't do this then 如果它没有这样做那么

B.Next = (B = null)

Would be a null reference exception which wouldn't be what you would expect would it? 将是一个空引用异常,它不会是你期望的那样吗?

This behavior is not a result of operator precedence, but of rules in Java, Python, and C# which define the order of evaluation of expressions. 此行为不是运算符优先级的结果,而是Java,Python和C#中定义表达式求值顺序的规则的结果。 Specifically, in Java, Python, and C#, expressions are evaluated left to right. 具体来说,在Java,Python和C#中,表达式从左到右进行计算。 This isn't true, for example, in C and C++, where the result of what you wrote would have been undefined. 例如,在C和C ++中,这是不正确的,其中您编写的结果将是未定义的。

You might be familiar with this C puzzle: 您可能熟悉这个C拼图:

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

In C, the result is not defined. 在C中,结果未定义。 It could be 1, 3 , it could be 2, 2 , or even something else. 它可能是1, 3 ,它可能是2, 2甚至是其他东西。 In Java C#, and Python, the result is always 1, 3 (except of course that Python does not have a pre- or postfix ++ operator). 在Java C#和Python中,结果总是1, 3 (当然除了Python没有pre或postfix ++运算符)。

Operator precedence is a separate issue. 运算符优先级是一个单独的问题。 It defines the parse tree, not the order of evaluation. 它定义了解析树,而不是评估顺序。

Say you had a new language with binary infix operators op1 and op2 . 假设您使用二进制中缀运算符op1op2的新语言。 And say you had the following piece of code: 并说你有以下代码:

e1 op1 e2 op2 e3

Operator precedence tells you whether this means 运算符优先级告诉您这是否意味着

((e1 op1 e2) op2 e3)

Or whether it means 或者是否意味着

(e1 op1 (e2 op2 e3))

It does not tell you the order in which e1 , e2 , and e3 are evaluated. 没有告诉您评估e1e2e3的顺序。

For completeness, Java works here the same like C#. 为了完整起见,Java在这里像C#一样工作。

    Node A = new Node();

Creates a new node (let's name it Node 1), and lets A point to it. 创建一个新节点(让它命名为Node 1),然后让A指向它。

    Node B = A;

This lets B point to the same Node 1. 这使B指向同一个节点1。

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

This is the situation now. 这就是现在的情况。 So, now the complicated last line: 那么,现在复杂的最后一行:

    B.Next = 

This changes the next-pointer of Node 1 (to which B pointed) to ... 这会将节点1的下一个指针(B指向的)更改为......

       (B=new Node());

... a new node (lets call it Node 2), which is at the same time put into the B variable. ...一个新节点(让我们称之为节点2),同时放入B变量。

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

The interesting thing here is, that the B.next is evaluated before the right side of the assignment, so it is the same as if you wrote A.next here. 这里有趣的是, B.next在赋值的右侧之前进行求值,因此它与在此处编写A.next的相同。

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

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