“在不使用第三个变量的情况下交换两个变量的值”中的潜在问题

发布于 2024-09-24 03:22:21 字数 152 浏览 4 评论 0原文

我最近提出了这种方法,可以在不使用第三个变量的情况下交换两个变量的值。

a^=b^=a^=b

但是当我在不同的编译器上尝试上面的代码时,我得到了不同的结果,有些给出了正确的结果,有些则没有。

代码有什么严重错误吗?

I recently came along this method for swapping the values of two variables without using a third variable.

a^=b^=a^=b

But when I tried the above code on different compilers, I got different results, some gave correct results, some didn't.

Is anything terribly wrong with the code?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

七禾 2024-10-01 03:22:21

代码有什么严重错误吗?

是的!

a^=b^=a^=b 实际上会调用 C 和 C++ 中的未定义行为,因为您试图在两个序列之间多次更改 a 的值点。


尝试用书写(尽管不是万无一失)

a ^= b;
b ^= a;
a ^= b;

代替a^=b^=a^=b

PS:切勿尝试在不使用第三个变量的情况下交换两个变量的值。始终使用第三个变量。

编辑

@caf注意到b^=a^=b^= 运算符的参数求值顺序,> 也可以,因为表达式中对 b 的所有访问都用于计算最终值被存储在 b 中,行为已明确定义。

Is anything terribly wrong with the code?

Yes!

a^=b^=a^=b in fact invokes Undefined Behaviour in C and in C++ because you are trying to change the value of a more than once between two sequence points.


Try writing (although not foolproof )

a ^= b;
b ^= a;
a ^= b;

instead of a^=b^=a^=b.

P.S : Never try to swap the values of two variables without using a third one. Always use a third variable.

EDIT :

As @caf noticed b^=a^=b is fine even though the order of evaluation of arguments of ^= operator is unspecified, since all the accesses of b within the expression are being used to compute the final value that is being stored in b, the behaviour is well defined.

漆黑的白昼 2024-10-01 03:22:21

如果您使用 C++,为什么不在 STL 中使用交换算法呢?它非常适合此目的,并且它的作用非常清楚:

#include <algorithm>
using namespace std;

// ...

int x=5, y=10;    // x:5 y:10
swap(x,y);        // x:10 y:5

If you're using C++, why not use the swap algorithm in STL? It is ideal for this purpose and it's very clear what it does:

#include <algorithm>
using namespace std;

// ...

int x=5, y=10;    // x:5 y:10
swap(x,y);        // x:10 y:5
你的背包 2024-10-01 03:22:21

基于 R. & 的贡献sellibitze:

使用逗号运算符:

 (a^=b,b^=a,a^=b);

From text &维基百科:

“逗号运算符可用于将相关表达式链接在一起。逗号链接的表达式列表从左到右计算,最右边表达式的值是组合后的值它充当序列点。”

“序列点保证先前计算的所有副作用都已执行,并且后续计算的副作用尚未执行。它会删除未定义的内容。由于原始表达式的执行顺序不明确而产生的行为。”

Based on contributions from R. & sellibitze:

Use the comma operator:

 (a^=b,b^=a,a^=b);

From text & Wikipedia:

"The comma operator can be used to link the related expressions together. A comma-linked list of expressions is evaluated left-to-right and the value of the rightmost expression is the value of the combined expression. It acts as a sequence point."

"A sequence point guarantees that all side effects of previous evaluations will have been performed, and no side effects from subsequent evaluations have yet been performed. It removes the undefined behavior arising out of the unclear order of execution of the original expression."

夜唯美灬不弃 2024-10-01 03:22:21

我建议您对 c++ 使用 std::swap() 。

对于 c,请使用此宏。请注意,您需要先比较 a 和 b,否则当它们指向同一内存位置时,您将擦除该值并使其变为 0。

#define swap(a, b)  ((a) == (b) || (a) ^= (b), (b) ^= (a), (a) ^= (b))

I suggest that you use std::swap() for c++.

For c, use this macro. Notice that you need to compare a and b first, otherwise when they are point to the same memory location you will wipe out the value and it becomes 0.

#define swap(a, b)  ((a) == (b) || (a) ^= (b), (b) ^= (a), (a) ^= (b))
煮茶煮酒煮时光 2024-10-01 03:22:21

这样做:

a ^= b;
b ^= a;
a ^= b;

Do it like this:

a ^= b;
b ^= a;
a ^= b;
节枝 2024-10-01 03:22:21

这个呢?

a = a + b;
b = a - b;
a = a - b;

What about this one?

a = a + b;
b = a - b;
a = a - b;
生死何惧 2024-10-01 03:22:21

我想知道为什么没有人建议在表达式中加上括号。看来已经不是UB了

a^=(b^=(a^=b));

I wondered why nobody suggested parenthesizing the expression. Seems it's not UB anymore.

a^=(b^=(a^=b));
骷髅 2024-10-01 03:22:21

您也可以尝试以下一种,但如果数字足够大,值就会溢出

a=a*b;
b=a/b;
a=a/b;

You can try the following one also, but if to numbers are large enough value will overflow

a=a*b;
b=a/b;
a=a/b;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文