【问题标题】:Swap integers via XOR in single line. Is it really allowed in c++11?通过 XOR 在单行中交换整数。 c++11真的允许吗?
【发布时间】:2015-06-01 15:13:06
【问题描述】:

我仍然无法清楚地理解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

【问题讨论】:

  • 不,它没有明确定义。分析与this question中的i += ++i + 1非常相似。
  • 我可以为您的理智提出建议吗?别再浪费时间去想这样的事情了。不管真正的答案是什么,知道它不会以任何方式改善你作为程序员的生活。
  • @BenjaminLindley 我很确定了解 UB 以及引入它的陷阱至关重要。
  • @Columbo:当然可以,一般来说。但不是在这种特殊情况下。在这种特殊情况下,您只需要知道这是一种编写代码的愚蠢方式,所以不要这样做。那么是不是UB的问题就无关紧要了。

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


【解决方案1】:

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

因此您的代码相当于

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

... x 在x = x ... 中只计算一次。 不幸的是,对于异或,操作数的评估是无序的。 IE。

除非另有说明,否则对单个运算符的操作数进行求值 和单个表达式的子表达式是无序的。

适用。但是现在我们有一个问题:

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

值计算(隐含在对最左边的两个xx 的奇异评估中)和副作用是无序的,因此我们引入UB:

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

【讨论】:

  • 但是如果第一个版本是UB,它仍然没有真正回答
  • 我开始倾向于两种结构都是 UB
猜你喜欢
  • 1970-01-01
  • 2012-07-04
  • 2016-04-05
  • 1970-01-01
  • 1970-01-01
  • 2013-05-08
  • 1970-01-01
  • 2013-07-13
  • 2021-10-15
相关资源
最近更新 更多