用异或交换两个整数的陷阱

本文揭示了使用异或运算交换数组元素时的潜在陷阱,特别是当试图交换同一元素自身时,可能导致意外的结果。文章提供了解决方案,确保在交换操作中考虑相同元素的情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前面我们谈到了,可用通过异或运算交换两个数,而不需要任何的中间变量。 如下面:

void exchange(int &a, int &b)
{
    a ^= b;
    b ^= a;
    a ^= b;
}


然而,这里面却存在着一个非常隐蔽的陷阱。


通常我们在对数组进行操作的时候,会交换数组中的两个元素,如exchang(&a[i], &b[j]), 这儿如果i==j了(这种情况是很可能发生的),得到的结果就并非我们所期望的。


void main() 
{
   int a[2] = {1, 2};
   exchange(a[0], a[1]); //交换a[0]和a[1]的值
   printf("1---a[0]=%d a[1]=%d\n", a[0], a[1]);
   exchange(a[0], a[0]); //将a[0]与自己进行交换
   printf("2---a[0]=%d a[1]=%d\n", a[0], a[1]);
}
 上面那段测试代码的输出是:
1---a[0]=2 a[1]=1
2---a[0]=0 a[1]=1
很意外吧,第一次的交换正确的执行了,但是第二次调用exchange的时候却将a[0]置为了0. 仔细分析,不难发现,这正是我们在exchange里面用异或实现交换所造成的。如果输入a和b是同一个数,exchange里面代码相当于:


a ^= a;
a ^= a;
a ^= a;
成了a做了3次于自己的异或,其结果当然是0了。


既然这样,我们就不能够在任何使用交换的地方采用异或了,即使要用,也一定要在交换之前判断两个数是否已经相等了,如下:


    void exchange(int &a, int &b)
    {
        if(a == b) return; //防止&a,&b指向同一个地址;那样结果会错误。
        a ^= b;
        b ^= a;
        a ^= b;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值