从一段代码看异或的用途

今天看到了ELF hash算法的实现,里面有个异或操作


#include <stdio.h>

unsigned int elfhash( char * str)
{
    unsigned int hash = 0 ;
    unsigned int x = 0 ;
    while ( * str)
    {
        hash = (hash << 4 ) + ( * str ++ );
        if ((x = hash & 0xF0000000L ) != 0 )
        {
            hash ^= (x >> 24 );
            hash &= ~ x;
        }
    }
    return (hash & 0x7FFFFFFF );
}

int main(int argc, char *argv[])
{

    printf("%s::%p\n", argv[1], (void *)elfhash(argv[1]));

    return 0;
}

当32位的数的最高4位不为零时,进行特殊处理,防止下一次循环时溢出:

1. 把hash变量的最高的4位与5-8位进行异或

2. 然后再把hash变量的最高4位清零


处理完毕后,返回时先进行与操作,把最高位清零。

如果定义的是无符号整型数据,可以不用这一步(hash的高4位已经清零,没必要再来一次与操作)。


整个运行过程就是这样,但是好像有些值的ELF hash算法的结果一样:

如fffffffffffffffffffffffffffffff 和ffffffffffffffffffffffff 最后生成key的结果保证一样,但是在实际中不太可能出现。


读完这个例子,顺使总结了异或操作的用途:


1. 翻转某些特定位,常用于硬件操作的特殊寄存器对某一位采取翻转操作的情形。

    a ^= (1 << n)  对a的第n位进行翻转

    有人说异或可以实现取返的操作,比如32位,~a 的值相当于a^0xFFFFFFFF,不过我感觉如果当天吃的比较多,可以用异或来取返,一般情况下~a看起来要更简单一些。


2. 实现两个值交换

    如a=4, b=5

    a ^=b; b^=a; a^=b;

   操作之后,a=5, b= 4

   这种操作可以保证数据不溢出。有人说了,用加法也可以使得两个数交换,那样可能会产生数据溢出。


3. 将某位数置零,异或本身

    a^=a;

    MIPS汇编大概有这几种解决方法。

    li $t0 0   ;把立即数0放在$t0寄存器中

   move $t0 $zero  ;这是利用MIPS的$zero寄存器始终为0的简化操作

   addu $t0 $zero $zero ;用加法也可以实现赋值操作

   xor $t0 $t0 $t0  ;自己异或,结果为0

   这一条语句在MIPS汇编中有多种实现,看来还是非常灵活的。


4. 快速判断两个值是否相等

    return (a^b == 0)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值