运算符优先级
考虑一下这个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 个回答
2
在Python中,你不能像你那样把多个赋值放在一起。最右边的值会被赋给它左边的所有变量。
>>> 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>
2
C# 在处理赋值时是从左到右进行的。
所以在你的第二个例子中,它首先会“计算”赋值左边的部分(B.Next),然后再去计算右边的部分,最后得到 A 中的 Next 的引用。
你在右边做的任何操作,都是赋值给左边的这个部分。所以如果你在右边改变 B,那就已经太晚了。
如果不是这样的话,
B.Next = (B = null)
就会出现空引用异常,这可不是你所期待的,对吧?
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没有前缀或后缀的++运算符)。
运算符的优先级是另一个问题。它定义的是解析树,而不是计算的顺序。
假设你有一种新的语言,里面有二元中缀运算符op1
和op2
。假设你有以下这段代码:
e1 op1 e2 op2 e3
运算符优先级告诉你这段代码是意味着
((e1 op1 e2) op2 e3)
还是意味着
(e1 op1 (e2 op2 e3))
但它并不告诉你e1
、e2
和e3
的计算顺序。