I am trying to replace the following piece of code
// code version 1
unsigned int time_stx = 11; // given range start
unsigned int time_enx = 19; // given range end
unsigned int time = 0; // desired output
while(time_stx < time_enx) time |= (1 << time_stx++);
with the following one without a loop
// code version 2
unsigned int time_stx = 11;
unsigned int time_enx = 19;
unsigned int time = (1 << time_enx) - (1 << time_stx);
It turns out that in code version 1, time = 522240;
in code version 2, time = 0;
when I use
printf("%u\n", time);
to compare the result. I would like to know why is this happening and if there is any faster way to toggle bits in a given range. My compiler is gcc (Debian 4.9.2-10) 4.9.2.
Edit:
Thank you for your replies. I have made a silly mistake and I feel embarrassing posting my question without further inspecting my codes. I did
unsigned int time_stx = 11;
unsigned int time_enx = 19;
unsigned int time1 = 0;
while(time_stx < time_enx) time1 |= (1 << time_stx++); // version 1
//// what I should, but forgotten to do
// time_stx = 11;
// time_enx = 19;
// where time_stx = time_enx now...
unsigned int time2 = (1 << time_enx) - (1 << time_stx); // version 2
// then obviously
printf("time1 = %u\n", time1); // time1 = 522240
printf("time2 = %u\n", time2); // time2 = 0
I am so sorry for any inconvenience incurred.
Remark: both time_stx
and time_enx
are generated in the run-time and are not fixed.
As suggested that I made a mistake and the problem is solved now. Thank you!!
Read Bit twiddling hacks. Even if the answer isn't in there, you'll be better educated on bit twiddling. Also, the original code is simply setting the bits in the range; toggling means turning 1 bits into 0 bits and vice versa (normally achieved using
^
or xor).As to the code, I converted three variants of the expression into the following C code:
When I look at the assembler for it (GCC 5.1.0 on Mac OS X 10.10.3), I get:
That's an amazingly large collection of labels!
The compiler has fully evaluated all three minimal
bit_setterN()
functions and inlined them, along with the call toprint
, into the body ofmain()
. That includes evaluating the expressions to 522240 each time.Compilers are good at optimization. Write clear code and let them at it, and they will optimize better than you can. Clearly, if the 11 and 19 are not fixed in your code (they're some sort of computed variables which can vary at runtime), then the precomputation isn't as easy (and
bit_setter3()
is a non-starter). Then the non-loop code will work OK, as will the loop code.For the record, the output is:
If your Debian compiler is giving you a zero from one of the code fragments, then there's either a difference between what you compiled and what you posted, or there's a bug in the compiler. On the whole, and no disrespect intended, it is more likely that you've made a mistake than that the compiler has a bug in it that shows up in code as simple as this.