现在的位置: 首页 > 综合 > 正文

异或操作交换元素容易产生的问题

2013年09月14日 ⁄ 综合 ⁄ 共 825字 ⁄ 字号 评论关闭

零.Introduction

利用异或操作交换两个元素已不是什么新鲜话题了。

1异或写法:

{
    a ^= b;
    b ^= a;
    a ^= b;
}

2传统写法:

{
    int temp = a;
    a = b;
    b = temp;
}

有很多程序员已经逐渐接受并喜欢使用这种异或写法了,问之优点,大多数程序员都会从时间性能,空间性能,简洁性三方面做回答。由于位操作较赋值操作的确快了些,空间上仅仅节约一个单位,至于简洁性就有点牵强了(明显差不多嘛),可读性反倒降低了,我觉得大多数程序员采用异或写法有部分因素是因为觉得这种写法比较酷。但为了这点酷,我们可能要在正确性等方面投入很多精力,付出更多的代价。

一.类型适用性

传统的赋值写法可适用于多种类型,其正确性也是毋庸置疑的。而异或写法除了整型之外,不敢保证其疑惑操作符在作用与浮点或自定义类型时还能正确的工作。如果不想证明的话,那就老老实实使用传统写法吧。

二.正确性

在使用中交换操作往往被提取成swap函数,按照两种写法分别如下:

1.异或写法

void swap(int* a, int* b){
    *a ^= *b;
    *b ^= *a;
    *a ^= *b;
}

2.传统写法

void swap(int* a, int* b){
    int t = *a;
    *a = *b;
    *b = t;
}

实参调用往往是这样swap(&num1, &num2);一般情况下两种写法都能正确工作。但是考虑如下情况:

    int a = rand();
    int* p1 = &a;
    int* p2 = &a;
    swap(p1, p2);

当两个指针变量指向同一个地址的数据时,只有传统写法可以工作。
究其原因传统写法把地址上的值取了出来,而异或写法直接在原地址上进行值运算,一次异或之后值就成了0,两个指针都指向这个地址,后面再怎么异或也只能是0了。可以画个图来试试。

在应用中,如果要使用异或写法来交换元素,就得确保所传两个地址不一样,否则就会出现这话总错误。

为了一点酷,一个单位空间的节省,极少的时间性能增益,可读性降低了,正确性的风险更大了,操的心多了,试问,还有必要那么写吗?

抱歉!评论已关闭.