数据归零时奇怪的异或交换行为

Weird XOR swap behavior while zeroing out data

本文关键字:交换 换行 归零 零时 数据      更新时间:2023-10-16

谢谢Doug。修复方法如下:

void swap(int& a, int& b) {
    if (&a == &b) // added this check to ensure the same address is not passed in
        return;
    a ^= b;
    b ^= a;
    a ^= b;
}


我在c++中实现快速排序,我使用整数作为虚拟数据。我一直在使用异或交换算法来交换两个值,但我注意到我的排序搞砸了。我改变了交换算法,它起作用了。我添加了一些调试语句,发现异或交换做了一些奇怪的事情。

我在交换之前和之后打印了数据,下面是它打印的内容:

...
swapping -5, -3
swapped  -3, -5
swapping -5, -5
swapped  0, 0     <---- What?
swapping -2, -4
swapped  -4, -2
...
下面是我的代码:
// this might not be that great or even work as intended but it doesn't really matter for this problem
int av3index(int a[], int indx1, int indx2, int indx3) {
    if (a[indx3] <= max(a[indx1], a[indx2]) && a[indx3] >= min(a[indx1], a[indx2]))
        return indx3;
    if (a[indx2] <= max(a[indx1], a[indx3]) && a[indx2] >= min(a[indx1], a[indx3]))
        return indx2;
    if (a[indx1] <= max(a[indx2], a[indx3]) && a[indx1] >= min(a[indx2], a[indx3]))
        return indx1;
}
void swap(int& a, int& b) {
    /*
    This works
    int tmp = b;
    b = a;
    a = tmp;*/
    cout << "swapping " << a << ", " << b << endl;
    a ^= b;
    b ^= a;
    a ^= b;
    cout << "swapped  " << a << ", " << b << endl << endl;
}
void zqsort(int a[], int len) {
    if (len <= 1)
        return;
    int pivot = av3index(a, 0, len / 2, len - 1);
    swap(a[pivot], a[0]);
    int i = 1, j = len - 1;
    while (i <= j) {
        if (a[i] > a[0]) {
            while (i <= j && a[j] > a[0])
                --j;
            if (i <= j)
                swap(a[i], a[j]);
        }
        ++i;
    }
    swap(a[0], a[j]);
    zqsort(a, len / 2);
    zqsort(a + len / 2, len - len / 2);
}
int main() {
    int values[] = {5, 4, 3, 2, 1, 0, -1, -2, -3, -4, -5};
    int len = sizeof(values) / sizeof(int);
    int* arr = new int[len];
    for (int i = 0; i < len; ++i)
        arr[i] = values[i];
    zqsort(arr, len);
    cout << "sorted array:" << endl;
    for (int i = 0; i < len; ++i)
        cout << arr[i] << endl;
    cin.get();
}

我没有使用任何参考的快速排序代码,所以它可能是错误的,但我不认为这是密切相关的问题。

您的交换ab是相同的位置。异或攻击只在不同位置时有效。

I think in C;这是一个表格:

           &a != &b  &a == &b
           *a   *b   *a   *b
           -5   -5   -5   -5
*a ^= *b;   0   -5    0    0
*b ^= *a;   0   -5    0    0
*a ^= *b;  -5   -5    0    0

除了现有的答案,我只是补充一下,如果你要在交换之前做一个测试,那么你不妨改变:

if (&a == &b) // added this check to ensure the same address is not passed in
    return;

:

if (a == b) // check that values are different
    return;

这将处理&a == &ba == b的情况,这可能会节省一些不必要的交换

任何与自身相异的东西都是零。