按位运算 求前0和后0的个数

今天看到一个比较有意思的c按位运算求二进制前0的个数。开始我也没有懂起,后来多次实验,才摸到套路,理一个思路,供大家参考。

int x264_clz(uint32_t x)
{
    static uint8_t lut[16] = {4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0};
    int y, z = (((x >> 16) - 1) >> 27) & 16;  //通过右移16位将高位暴露出来, -1判断高位是否有1,如果有1, -1就被阻挡了, 不能改变高位逻辑右移补充的0,所以右移27位并&16就会等于0, 否在就等于16。
    //下面是低位-1,影响高位的说明,也是这个代码的难点,其实很简单。
    //低位有1, 高位失败,  如二进制, 0000,0100-1 = 0000,0011
    //低位没有1,高位成功, 如二进制, 0000,0000-1 = 1111,1111
    
    x >>= z ^ 16; //现在z的值是16或者0, 如果16就右移0位, 如果0就右移16位。
    z += y = ((x - 0x100) >> 28) & 8;//与上面类是。这里判断8位。
    x >>= y ^ 8;
    z += y = ((x - 0x10) >> 29) & 4;//与上面类是,这里判断4位。
    x >>= y ^ 4;
    return z + lut[x];//最低4位直接用上表lut进行判断。
}
static int ALWAYS_INLINE x264_ctz(uint32_t x)
{
    static uint8_t lut[16] = {4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0};
    int y, z = (((x & 0xffff) - 1) >> 27) & 16;//和上面的代码类是, 这里先看的低十六位,&0xffff将高16位置零,然后-1,查看1是否传到高位,如果传到高位,那低16位全是0,如果没有,就说明低位16位有1。 
    x >>= z;
    z += y = (((x & 0xff) - 1) >> 28) & 8;
    x >>= y;
    z += y = (((x & 0xf) - 1) >> 29) & 4;
    x >>= y;
    return z + lut[x & 0xf];
}

猜你喜欢

转载自blog.csdn.net/u012939880/article/details/90701434