以下是代码:
#include <stdio.h>
union
{
unsigned u;
double d;
} a,b;
int main(void)
{
printf("Enter a, b:");
scanf("%lf %lf",&a.d,&b.d);
if(a.d>b.d)
{
a.u^=b.u^=a.u^=b.u;
}
printf("a=%g, b=%g\n",a.d,b.d);
return 0;
}
如果a.u^=b.u^=a.u^=b.u;
,a
语句应该已交换b
和a>b
,但无论我输入什么,输出都将完全是我的输入。
答案 0 :(得分:2)
a.u^=b.u^=a.u^=b.u;
通过在没有序列点的情况下写入a.u
两次来导致未定义的行为。 See here讨论此代码。
你可以写:
unsigned tmp;
tmp = a.u;
a.u = b.u;
b.u = tmp;
将交换a.u
和b.u
。但是,如果double
比您系统上的unsigned
更大,则可能无法实现交换两个双打的目标(常见情况)。
答案 1 :(得分:1)
double
可能是64位,而unsigned
只是32位。当您更换工会的unsigned
成员时,您只能获得doubles
的一半。
如果您将d
更改为float
,或将u
更改为unsigned long long
,则可能会有效,因为它们的大小可能相同。
您还通过在没有序列点的情况下写入变量两次来导致UB。编写XOR交换的正确方法是使用多个语句。
b.u ^= a.u;
a.u ^= b.u;
b.u ^= a.u;
有关为何不使用XOR进行交换的详细信息,请参阅Why don't people use xor swaps?
答案 2 :(得分:0)
在通常的环境中,数据类型的内存大小&#39; unsigned&#39;和&#39; double&#39;是不同的。 这就是变量看起来不像改变的原因。
你不能在浮点变量上使用XOR交换。 因为它们在记忆中的表现完全不同。