[英]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也是如此吗? 谢谢
在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 ++运算符)。
运算符优先级是一个单独的问题。 它定义了解析树,而不是评估顺序。
假设您使用二进制中缀运算符op1
和op2
的新语言。 并说你有以下代码:
e1 op1 e2 op2 e3
运算符优先级告诉您这是否意味着
((e1 op1 e2) op2 e3)
或者是否意味着
(e1 op1 (e2 op2 e3))
它没有告诉您评估e1
, e2
和e3
的顺序。
为了完整起见,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.