为什么a和b在这段代码中没有交换?

时间:2015-11-26 01:03:15

标签: c unions bit-fields

以下是代码:

#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语句应该已交换ba>b,但无论我输入什么,输出都将完全是我的输入。

3 个答案:

答案 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.ub.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交换。 因为它们在记忆中的表现完全不同。