我有一个32位的字段,其中设置了一个位.如何获取该位的数字(如int或其他)?

示例(为简洁起见,使用8位):

Input              Desired output
0x01 / 00000001 -> 0
0x04 / 00000100 -> 2
0x08 / 00001000 -> 3
0x00 / 00000000 -> undefined/whatever
0x06 / 00000110 -> undefined/whatever

我在寻找简洁易读的代码或通用库函数,而不是最聪明或性能最好的解决方案.

推荐答案

您可以为此使用编译器内置.gccclang支持这一点:

内置功能:int __builtin_clz(unsigned int x)

返回从最高有效位位置开始的x中前导0位的数目.如果x0,则结果未定义.

int bit_index32(unsigned x) {
    return 31 - __builtin_clz(x);
}

要获得更具可移植性的解决方案,您可以使用一个简单的循环:

int bit_index32(unsigned x) {
    int n = 0;
    while (x > 1) { n++; x >>= 1; }
    return n;
}

速度更快,只需5次测试,而不是最多31次:

int bit_index32(unsigned x) {
    int n = 0;
    if (x > 0xFFFF) { n += 16; x >>= 16; }
    if (x > 0xFF)   { n +=  8; x >>=  8; }
    if (x > 0xF)    { n +=  4; x >>=  4; }
    if (x > 0x3)    { n +=  2; x >>=  2; }
    if (x > 0x1)    { n +=  1; x >>=  1; }
    return n;
}

由于v是2的幂,索引是v-1中的位数,无需测试即可计算:

int bit_index32(unsigned v) {
    v--;
    v = v - ((v >> 1) & 0x55555555);
    v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
    return ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24;
}

另一个只对2的幂起作用的无分支的:

int bit_index32(unsigned v) {
    return !!(v & 0xAAAAAAAA)
         | !!(v & 0xCCCCCCCC) << 1
         | !!(v & 0xF0F0F0F0) << 2
         | !!(v & 0xFF00FF00) << 3
         | !!(v & 0xFFFF0000) << 4;
}

肖恩·安德森的Bit Twiddling Hacks岁生日更有趣!

C++相关问答推荐

*p[num]和(*p)num的区别

为什么在C中进行大量的位移位?

两个连续的语句是否按顺序排列?

如果dim指定数组中的数据量,使用dim-1会不会潜在地导致丢失一个元素?

如何使用[BTStack]BLE发送大型(>;2kb)信息包

在循环中复制与删除相同条件代码的性能

Flose()在Docker容器中抛出段错误

为什么memcpy进入缓冲区和指向缓冲区的指针工作相同?

为什么中断函数会以这种方式影响数组?

这个C程序在工作中途停止获取输入.我收到分段故障(核心转储).我还是不知道问题出在哪里

cairo 剪辑区域是否存在多个矩形?

通过描述符查找文件路径时出现问题

如何在不使用字符串的情况下在c中编写函数atof().h>;

运行时错误:在索引数组时加载类型为';char';`的空指针

将 struct 数组写入二进制文件时发生Valgrind错误

如何在C中用bool进行文件I/O?

unions 的原子成员是个好主意吗?

在我的第一个C语言中观察到的错误';你好世界';程序

我正在使用 klib 库 我可以使用 (khash) KHASH_SET_INIT_INT64() 负值作为键.因为我在头文件中看到它使用 unsigned long int

模仿 memmove 的行为