指定基址,寻找已知偏移量到指定范围第一个'1'的位到该偏移量的距离(都以bit为单位)

已知条件:
基址base,搜索区间[offset,offset+width),求该区间第一个为’1’的位到offset的距离(以bit为单).

如下图示:





2.基本思路:

  1)获取第offset位所在变量,取该变量指针cp

  2)获取p到搜索的结束位总共需要检测的变量数num_valiable

  3)先把*cp右移使得offset位移到第0位,

  4)获取选中的num_valiable个变量里的第一个不为'0'的变量存入temp ,

  5)更新result(目前是temp变量的第0位到第一个变量的第0位的距离)

  6)使用二分查找算法来找到temp的第一个出现'1'的位 . (查找过程中实时更新ersult)

  7)判断该变量是否为第一个变量 ,  如果不是 , 还要把result减去之前移位第一个变量的位数 .

  8)返回result .



程序实现如下:

#include "stdio.h"
#include "stdlib.h"

unsigned int bit_search_first_one(void *base , unsigned int offset , unsigned int width);

int main()
{
    unsigned int i;
    unsigned int a[] = {0xf0f0f00f,0x08,0x0000,0xfff000f0};
    
    i = bit_search_first_one( a , 55 , 32);
    
    printf("i=%d\n",i);
    exit(0);

}
/*在基址p的位偏移[offset,offset+width)之间找到第一个为‘1’的位到offset的距离*/
unsigned int bit_search_first_one(void *base , unsigned int offset , unsigned int width)
{
    unsigned int *cp;
    unsigned int num_valiable;
    unsigned int temp;
    unsigned int num_temp;
    unsigned int result;

    cp = (unsigned int *)base;
    
    /*计算出offset的位所在的变量地址*/
    cp += (offset>>5);

    //计算从[offset,offset+width)占的变量数
    num_valiable = ((offset+width-1)>>5) +1 - (offset>>5);
    printf("num_valiable=%d\n",num_valiable);
    num_temp = num_valiable;

    /*offset所在的变量需要先移位把不需要比较的位移除 ,因为无符号右移补0,所以不会造成影响*/
    temp = (*cp)>>(offset&31);

    do{
        printf("temp=%d\n",temp);
        if(temp){   /*如果该变量有为‘1’的位,直接退出循环*/
            break;
        }
        cp++;
        temp = *cp;
    }while(--num_valiable);

    if(!num_valiable){   /*减到0,说明指定范围没有‘1’的位*/
        printf("ssss\n");
        return 0xffffffffl;
    }

    result = 32*(num_temp-num_valiable);
    
    if(!(temp&0xffff)){  //如果低16位都是0,那么与offset的偏移加16 , 把temp>>16位用于下面对高16位进行分割判断
                 //如果低16位有'1'的位,则直接对这16位再进行分割判断.
        result += 16;
        temp >>= 16;
    }

    if(!(temp&0xff)){   //同理
        result += 8;
        temp >>= 8;
    }

    if(!(temp&0xf)){    //同理
        result += 4;
        temp >>= 4;
    }

    if(!(temp&0x03)){   //同理
        result += 2;
        temp >>=2;
    }

    if(!(temp&0x01)){   //同理
        ++result;
    }

    if(num_valiable != num_temp){  /*不是在offset所在变量就存在‘1’位,需要减去之前对offset所在变量右移的位数*/
        result -= (offset&31);
    }
    
    return result;
}



你可能感兴趣的:(关于c语言的那些事)