【问题标题】:C++ XOR operator precendenceC++ XOR 运算符优先级
【发布时间】:2012-10-02 12:38:56
【问题描述】:

所以我在这里很困惑,是否: 是

 a ^= b^c 

相当于

 a = a ^ (b ^ c) 

还是a = (a ^ b) ^ c

【问题讨论】:

  • 你知道,阅读文档
  • 你试过了,看看结果如何?
  • here
  • 反正也没关系。

标签: c++ c


【解决方案1】:

任何短格式运算符:

LHS OP= RHS;

很像:

LHS = LHS OP RHS;

正如 cmets 中所指出的,完成的评估次数等存在差异,因此如果您在评估 LHS 时开始产生副作用,那么这种简单的等价就不再那么简单了。或同等学历。这就是为什么我重新措辞上面的措辞以使其不那么铁定。

所以是前者,即a = a ^ (b ^ c)

【讨论】:

  • @PaulR:怎么样? , c 不是该表达式中异或赋值的 RHS 的一部分,因此 LHS 是 a,RHS 是 b 并且展开的等价性成立,只是其中不应该有分号。更重要的是,提问者的表情呢?在那里,LHS 是a,RHS 是b^c,所以根据这个答案,它相当于a = a ^ b^c,但^ 从左到右关联。你应该写,LHS = (LHS OP (RHS))
  • @SteveJessop 匹配“a ^= b, c;”的唯一方法到模式“LHS OP = RHS;”是将“b,c”匹配到RHS。所以保罗的迂腐观点是准确的......“LHS = LHS OP RHS;”错了,“LHS = LHS OP (RHS);”也是错的
  • 这是不正确的,至少有两个原因。一,“LHS OP= RHS”对 LHS 求值一次,而“LHS = LHS OP RHS”对 LHS 求值两次。二是没有保持优先权; “a *= b+c”不等价于“a = a * b+c”,因为前者先计算“b+c”,而后者先计算“a * b”。
  • @SteveJessop 现在你有点迂腐了;这是一个有意义的问题。 “它无法正确解析 C 或 C++”——这是错误的。
  • 无论如何,我们确实在一个有 7 票反对的问题上付出了很多努力。我有点厌倦了使用 SO 代替手册、教程或课堂的人。
【解决方案2】:

“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 的补码实现几乎不存在,但标准允许它们。

重要的是,在abc 是整数的情况下,a -= b - c等同于a = (a - b) - c。除非c 等于0

【讨论】:

    【解决方案3】:

    想想异或真值表,试一试,这有关系吗?

    x | y | XOR
    -----------
    0 | 0 |  0
    1 | 0 |  1
    0 | 1 |  1
    1 | 1 |  0
    

    所以如果你说 b = 10; //1010c = 7; //0111a = 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)

    【讨论】:

    • 问题是关于 C++ 的。这很重要,因为operator^ 可能会超载。这也很重要,因为 ^= 遵循适用于所有赋值运算符的一般规则,而不仅仅是关联运算符。
    • @SteveJessop - 该问题同时具有 C 和 C++ 标签,如果两个标签都适用,则运算符^ 不能重载。另外这个问题没有运算符重载标签......所以这里的逻辑假设是非重载......但你是正确的,所以我会做出区分。
    • 我认为你是对的,提问者并没有为运算符重载做好准备,因为如果operator^= 被重载,那么第一个表达式可能不等于其他两个表达式。但我很确定问题不是真的关于 XOR 的属性,而是关于复合赋值运算符的解释。
    • @SteveJessop - 是的,我会给你那个,我可能有点太直白了。已更新。
    【解决方案4】:

    这里没有运算符优先级。您的问题是关于关联性的,并且由于运算符是关联的,因此没有任何区别。

    【讨论】:

    • 这里怎么没有优先级? C 标准非常明确地指出^ 的优先级高于^=
    • 实际上,答案需要同时关注优先级和关联性。它没有任何区别是因为^ 是可交换的。
    猜你喜欢
    • 2013-02-24
    • 2017-06-02
    • 1970-01-01
    • 2021-03-29
    • 2013-07-31
    • 2013-02-09
    • 2014-03-01
    相关资源
    最近更新 更多