【发布时间】:2012-10-02 12:38:56
【问题描述】:
所以我在这里很困惑,是否: 是
a ^= b^c
相当于
a = a ^ (b ^ c)
还是a = (a ^ b) ^ c?
【问题讨论】:
-
你知道,阅读文档。
-
你试过了,看看结果如何?
-
见here。
-
反正也没关系。
所以我在这里很困惑,是否: 是
a ^= b^c
相当于
a = a ^ (b ^ c)
还是a = (a ^ b) ^ c?
【问题讨论】:
任何短格式运算符:
LHS OP= RHS;
很像:
LHS = LHS OP RHS;
正如 cmets 中所指出的,完成的评估次数等存在差异,因此如果您在评估 LHS 时开始产生副作用,那么这种简单的等价就不再那么简单了。或同等学历。这就是为什么我重新措辞上面的措辞以使其不那么铁定。
所以是前者,即a = a ^ (b ^ c)。
【讨论】:
, c 不是该表达式中异或赋值的 RHS 的一部分,因此 LHS 是 a,RHS 是 b 并且展开的等价性成立,只是其中不应该有分号。更重要的是,提问者的表情呢?在那里,LHS 是a,RHS 是b^c,所以根据这个答案,它相当于a = a ^ b^c,但^ 从左到右关联。你应该写,LHS = (LHS OP (RHS))。
“C 和 C++”涵盖了很多领域,但举个例子,C99 标准说 (6.5.16.2):
E1 op= E2形式的复合赋值不同于简单的赋值 赋值表达式E1 = E1 op (E2)只是因为左值E1是 只评估一次。
在 C++ 中,运算符重载意味着第一个表达式可能不等于其他两个表达式,具体取决于操作数的类型。但是对于内置的复合运算符,同样的规则也适用。 C++03 说(5.17/7):
E1 op= E2形式的表达式的行为等价于E1 = E1 op E2除了E1只计算一次。
请注意,只有 C 标准才会费心包含必要的括号来直接回答您的问题:名义上是 a ^ (b ^ c) 而不是 (a ^ b) ^ c。
但我认为我们可以假设在 C++ 标准在这里使用的特设的类似 BNF 的语法语言中,诸如 E2 这样的 BNF 非终结符总是被认为是它出现的表达式的子表达式因此,在具有从左到右关联性的情况下(并且所有具有复合赋值版本的运算符都从左到右关联),这将拆分 E2 使其不再是子表达式,我们必须在心里插入足够的括号来防止这种情况发生。
实际上,XOR 并不重要,因为无论如何值都是相同的除非您在此过程中生成了一个陷阱表示,这会导致错误。这可能发生在 C 或 C++ 的非 2 补码实现上,并且这种情况的实现可能不将a ^= b^c 计算为a = (a^b)^c,即使它想要。非 2 的补码实现几乎不存在,但标准允许它们。
重要的是,在a、b、c 是整数的情况下,a -= b - c不等同于a = (a - b) - c。除非c 等于0。
【讨论】:
想想异或真值表,试一试,这有关系吗?
x | y | XOR
-----------
0 | 0 | 0
1 | 0 | 1
0 | 1 | 1
1 | 1 | 0
所以如果你说 b = 10; //1010 和 c = 7; //0111 和 a = 3; //0011
b ^ c = 1010 ^ 0111 = 1101
a ^ (b^c) = 0011 ^ 1101 = 1110 (14)
a ^ b = 0011 ^ 1010 = 1001
(a^b) ^c = 1001 ^ 0111 = 1110 (14)
鉴于您的具体示例,假设没有运算符重载,并且仅使用关联 XOR 运算符......这并不重要。
不太具体
^= 首先应用,所以:
a ^= b^c 等价于a = a ^ (b^c)
【讨论】:
operator^ 可能会超载。这也很重要,因为 ^= 遵循适用于所有赋值运算符的一般规则,而不仅仅是关联运算符。
operator^= 被重载,那么第一个表达式可能不等于其他两个表达式。但我很确定问题不是真的关于 XOR 的属性,而是关于复合赋值运算符的解释。
这里没有运算符优先级。您的问题是关于关联性的,并且由于运算符是关联的,因此没有任何区别。
【讨论】:
^ 的优先级高于^=。
^ 是可交换的。