WTL
WTL

Reputation: 113

Looping through Bits C

I'm trying to loop through the bits of an unsigned char, but I'm not sure where to start, eventually, I'll perform other bitwise operating on the bits, such as ~ and xor..etc.

Upvotes: 5

Views: 17599

Answers (6)

James Bush
James Bush

Reputation: 1525

This method allows maps the indicies of an array with values in an enumerator, regardless of the order of elements or how many elements are stored in the array:

typedef NS_OPTIONS(uint8_t, CaptureDeviceConfigurationControlPropertyBit) {
    CaptureDeviceConfigurationControlPropertyBitTorchLevel       = 1<< 0,
    CaptureDeviceConfigurationControlPropertyBitLensPosition     = 1<< 1,
    CaptureDeviceConfigurationControlPropertyBitExposureDuration = 1<< 2,
    CaptureDeviceConfigurationControlPropertyBitISO              = 1<< 3,
    CaptureDeviceConfigurationControlPropertyBitZoomFactor       = 1<< 4,
};

typedef CaptureDeviceConfigurationControlPropertyBit CaptureDeviceConfigurationControlPropertyBitMask;
CaptureDeviceConfigurationControlPropertyBitMask mask = (CaptureDeviceConfigurationControlPropertyBitTorchLevel |
                                                         CaptureDeviceConfigurationControlPropertyBitLensPosition|
                                                         CaptureDeviceConfigurationControlPropertyBitExposureDuration|
                                                         CaptureDeviceConfigurationControlPropertyBitISO|
                                                         CaptureDeviceConfigurationControlPropertyBitZoomFactor);
                                                             
do{
    printf("mask\t==\t%d\n", (CaptureDeviceConfigurationControlPropertyBitMask)mask);
} while((mask ^= mask & (0- mask)) != 0.0);

Upvotes: 0

milevyo
milevyo

Reputation: 2180

#define BIT(a,b)    (a & (1<<b))

void printBits(unsigned char c){
    int i;

    char bits[9];
    for( i=0;i<8;i++){
        bits[i]=BIT(c,i)?'1':'0';

    }
    bits[8]=0;
    char *fmt=isalpha(c)
            ?"'%c'\t= '%s'\n"
            :" %d\t= '%s'\n";
    printf(fmt,c,bits);
}


int main(){


    printBits('A');
    printBits('B');
    printBits(1);
    printBits(2);
    printBits(3);
    return 0;
}

Upvotes: 0

Ze Blob
Ze Blob

Reputation: 2957

This function will allow you to iterate through all set bits in a word:

inline size_t next_bit(uint64_t bf, size_t bit) {
    return ctz(bf & ~((1UL << bit) -1));
}

The ctz function counts the number of trailing zeroes which should be provided by your compiler as a built-in function. For gcc and llvm, you can use the following (note that ctz is undefined for 0 on x86 hence the fixup):

inline size_t ctz(uint64_t x) { return x ? __builtin_ctzll(x) : 64; }

Here's an example of how to use it in a for-loop:

for (size_t i = next_bit(bf, 0); i < 64; i = next_bit(bf, i + 1))
    // the i-th bit is set.

The function works by clearing away all the bits preceding the ith bit and counting the number of trailing zeroes which will provide you with the next set bit after the ith bit. Clearing the bits is accomplished by first shifting a bit into the ith position, subtracting one which sets all the bits lower then the ith bit. We can then NOT the mask to get all the bits after i so that an AND op will remove all the bits after i. ctz does the rest.

It's a bit (pun intended) overkill for an unsigned char but I couldn't resist. Honestly, for 8-bit words, you're better off with a simple while loop as proposed in the other answers.

Upvotes: 2

Vikas.Ghode
Vikas.Ghode

Reputation: 33

Void PrintBits(unsigned int no)
{
Unsigned int mask = 0x8000;//=1000 0000 0000 0000 for 16 bit integers
For(I=0;I<16;I++){
    If((i&mask)!=0)printf("1");
    Else printf ("0");
    Mask>>=1;
    If(i%4==0)printf (" ");
}

}

If you don't understand this code please comment, I'm 24x7 online for you.

Upvotes: -1

ShadowRanger
ShadowRanger

Reputation: 155438

Well, from lowest to highest bit, you can loop like so:

unsigned char somebyte = ...;
for (int i = 0; i < 8; ++i, somebyte >>= 1) {
    if (somebyte & 0x1) {
        // Do stuff for 1 bit
    } else {
        // Do stuff for 0 bit
    }
}

That's a really general use case though; typically, you want to parallelize your work (operate on a whole byte at a time), or only operate on the 1 bits (and stop when you run out instead of finishing all eight loops), etc. More context is needed to solve specific problems rather than general looping. Many specific problems are most efficiently solved with clever bit twiddling hacks.

Upvotes: 0

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726639

Looping over bits can be done in several ways:

  • You can do a destructive loop, when you shift the value, and test the initial or the final bit, depending on the order in which you would like to enumerate bits, or
  • You can do a non-destructive loop, when you use bitwise AND to test the number with a single-bit mask, produced by left-shifting 1.

Here is an example of the first approach:

unsigned int bits = ...;
while (bits) {
    if (bits & 1) {
        // Current bit is set to 1
    } else {
        // Current bit is set to 0
    }
    bits >>= 1;
}

If you want to continue working with bits after you reach zero, make a separate counter.

Here is an example of the second approach:

unsigned int bits = ...;
for (int pos = 0 ; pos != 16 ; pos++) {
    if (bits & (1 << pos)) {
        // Current bit is set to 1
    } else {
        // Current bit is set to 0
    }
}

Upvotes: 12

Related Questions