Home > Back-end >  Get number of sole bit in bitfield
Get number of sole bit in bitfield

Time:05-30

I have a 32-bit bitfield where a single bit is set. How can I get the number of this bit (as int or something)?

Examples (using 8 bit for brevity):

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

I'm looking for succinct and readable code or common library functions, not for the most clever or best performing solution.

CodePudding user response:

You can use a compiler builtin for this. gcc and clang support this:

Built-in Function: int __builtin_clz(unsigned int x)

Returns the number of leading 0-bits in x, starting at the most significant bit position. If x is 0, the result is undefined.

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

For a more portable solution, you can use a simple loop:

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

A faster one with just 5 tests instead of up to 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;
}

Since v is a power of 2, the index is the number of bits in v-1, which can be computes without tests:

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

Another branchless one that only works for powers of 2:

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

More fun at Sean Anderson's Bit Twiddling Hacks!

CodePudding user response:

Shift one bit at a time until its in the low position and increment a counter each time.

int get_bit_num(uint32_t n)
{
    int count = 0;
    while (n>1) {
      n >>= 1;
      count  ;
    }
    return count;
}
  •  Tags:  
  • c
  • Related