通过XOR在单行中交换整数。在c ++ 11中真的允许吗?

时间:2015-03-28 08:27:54

标签: c++ c++11 language-lawyer undefined-behavior

我仍然无法清楚地了解表达式x ^= y ^= x ^= y; 在C ++ 11中有效(正如他们在thread中所说的那样)或者它会导致未定义的行为?

该链接给出的理由似乎令人信服,但clang抛出warning

  

警告:未经测试的修改和访问'x'[-Wunsequenced]

此外,如果两个版本:

x ^= y ^= x ^= y; // (1) 
x = x ^ (y = y ^ (x = (x ^ y))); // (2)

被认为是等效的(并且在C ++ 11中定义明确),为什么它会给出不同的结果(firstsecond)?

此外,应该注意的是,gcc仅在第二版代码上提供warning序列点。

1 个答案:

答案 0 :(得分:11)

  

赋值运算符(=)和复合赋值运算符all   小组从右到左。 [..]
  除E1 op = E2之外,E1 = E1 op E2形式的表达式的行为等同于E1   只评估一次。

因此,您的代码等同于

x = x ^ (y ^= (x ^= y)));

... x在x = x ...中仅评估一次。 不幸的是,对于xor,操作数的评估是不确定的。即

  

除非另有说明,否则评估各个运营商的操作数   并且个别表达的子表达式没有被排除。

适用。但现在我们遇到了一个问题:

   x = x ^ (y ^= (x ^= y)));
//     *          ******
//     |            |
//     |            Side effect
//     Value computation

值计算(对于最左边的两个x的{​​{1}}的单数评价中暗示)和副作用彼此不相关,因此我们诱导UB:

  

如果标量对象的副作用相对于其中任何一个都没有排序   对同一标量对象或值计算的另一个副作用   使用相同标量对象的值,行为未定义。