基址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;
}