Earlier quoted context omitted.
There are quite a lot of bit hacks on the web, but Hackers Delight is where it took off for me.It was a massive eye-opener, what was possible and even better doing it the old-fashioned way. The second book is very, very heavy on division and as such it's not really as much 'fun' as the original, however I'd still recommend it! I shared the original Hackers delight with a work colleague, who had a mathematical bent an…
The second book is very, very heavy on division and as such it's not really as much 'fun' as the original, however I'd still recommend it! What do you mean by this? Did they merely add a ton of information on division? Or did they take out the 'fun' bits from the original and replace them with division stuff?
Demystifying bitwise operations, a gentle C tutorial
81–90 of 95 posts
Re: Demystifying bitwise operations, a gentle C tutorial
#82I’ve found significant code in c/c++ where bitwise operations are done for things like division etc by shifting a certain way. I Can imagine in the past, this was “faster”, yet clang/gcc can emit the same by just writing a basic A/B function. Seems the win goes to readability by reducing some of these old school hacks. What say you, greybeards ?
One thing to consider is that the compiler can't simply replace a division by just a right shift for signed variables (it will round towards -inf for negative numbers), so even today there's a tiny bit of benefit of explicitly using shifts if you know that the number can't be negative (and the compiler can't prove it) or you don't care about the rounding ( https://godbolt.org/z/vTzYYxqz9 ). Of course that tiny bit of…
Re: Demystifying bitwise operations, a gentle C tutorial
#83The bitwise XOR operator (^) is a binary operator that compares the corresponding bits of two operands and returns a new value where each bit is set to 1 if the corresponding bits of the operand are different, and 0 if they are the same. You may also think about XOR in a following way: Any “1” in B flips (inverts) the corresponding bit in A. It’s like a vectorized NOT operation for single bits. Also works the other w…
Ob010 + 0b011 = 0b101 (carry is propagated to the 3rd bit)
0b010 ^ 0b011 = 0b001 (same result with no carry)Re: Demystifying bitwise operations, a gentle C tutorial
#84How do you count the number of bits which have been set in a bitfield of type uint32_t?
I couldn't find any x64_64 intrinsics for this, which would probably be incredibly efficient.
Re: Demystifying bitwise operations, a gentle C tutorial
#85This is great. However, he omitted one I encountered a need for pretty recently and have so far not found a good solution: How do you count the number of bits which have been set in a bitfield of type uint32_t? I couldn't find any x64_64 intrinsics for this, which would probably be incredibly efficient.
Re: Demystifying bitwise operations, a gentle C tutorial
#86This is great. However, he omitted one I encountered a need for pretty recently and have so far not found a good solution: How do you count the number of bits which have been set in a bitfield of type uint32_t? I couldn't find any x64_64 intrinsics for this, which would probably be incredibly efficient.
Re: Demystifying bitwise operations, a gentle C tutorial
#87This is great. However, he omitted one I encountered a need for pretty recently and have so far not found a good solution: How do you count the number of bits which have been set in a bitfield of type uint32_t? I couldn't find any x64_64 intrinsics for this, which would probably be incredibly efficient.
Like bluesnowmonkey says, the concept you're looking for is called popcount, for population count. It's also called the Hamming weight. Wikipedia has 5 different example implementations under that latter name. Many C/C++ compilers have it available as an intrinsic as well, like __builtin_popcount or __popcnt. It's also std::popcount in C++20.
// 19 instructions, does not use intrinsics
int countbits(unsigned x) {
unsigned n;
n = (x >> 1) & 0x77777777;
x = x - n;
n = (n >> 1) & 0x77777777;
x = x - n;
n = (n >> 1) & 0x77777777;
x = x - n;
x = (x + (x >> 4)) & 0x0F0F0F0F;
x = x\*0x01010101;
return x >> 24;
}
Amazing tip, thanks.Re: Demystifying bitwise operations, a gentle C tutorial
#88Earlier quoted context omitted.
All warnings are uninteresting until they're not. > ("strncmp takes const char star, did you really mean to pass it unsigned char star") This warning (with a different function) actually saved my bacon once, pointing me to a very obscure bug in the code. My practice is to use -Wall and make sure that the code compiles without any warnings at all. Then I don't have a deluge of warnings to wade through.
Remember -Wall isn't all. -Wall -Wextra is the new -Wall. I recommend asan too, where possible.
Re: Demystifying bitwise operations, a gentle C tutorial
#89Earlier quoted context omitted.
This is one case where lining up values (and surrounding operators with spaces) can be good practice: tx_data[43] = utime >> 24; tx_data[44] = utime >> 16; tx_data[45] = utime >> 8; tx_data[46] = utime >> 0; Or even: tx_data[43] = utime >> (3 * 8); tx_data[44] = utime >> (2 * 8); tx_data[45] = utime >> (1 * 8); tx_data[46] = utime >> (0 * 8);
I've done the >> 0 thing to make it very clear what's going on, but I hadn't considered the * 8 construction. That's actually easier to comprehend at a glance because the numbers become less "magic". (8 and 16 are obvious to me, but 24 always has me second-guessing myself somewhere in the back of my mind)
x
vs. x Re: Demystifying bitwise operations, a gentle C tutorial
#90I'm trying to find some good resources or some book that covers modern C. For everything else from Python to Golangz Rust and everything in between - there are tons of quality books and even their own documentation in some cases is pretty decent. But not so with C. If you read this and have something, please share. Just C (not much interested in C++)