问题
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.
回答1:
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
}
}
回答2:
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 i
th bit and counting the number of trailing zeroes which will provide you with the next set bit after the i
th bit. Clearing the bits is accomplished by first shifting a bit into the i
th position, subtracting one which sets all the bits lower then the i
th 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.
回答3:
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.
回答4:
#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;
}
回答5:
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.
来源:https://stackoverflow.com/questions/33005271/looping-through-bits-c