crisgoogle
6/8/2011 6:58:00 PM
On Jun 8, 11:05 am, pc <pranav.choudh...@gmail.com> wrote:
> Below is a snippet of code and the result (compiler version also
> mentioned). I fail to understand why the left shift operator behaves
> as if it were the left rotate operator when the operand is a variable.
>
> $ cat test.c
> #include <stdio.h>
> int main(void)
> {
> unsigned int a = 32, b = 33;
> printf("with constants 1 << 32 = %u, 1 << 33 = %u\n", 1<<32,
> 1<<33);
> printf("with variables 1 << 32 = %u, 1 << 33 = %u\n", 1<<a, 1<<b);
> return 0;}
>
> $ gcc test.c
> test.c: In function 'main':
> test.c:6:5: warning: left shift count >= width of type
> test.c:6:5: warning: left shift count >= width of type
> $ ./a.out
> with constants 1 << 32 = 0, 1 << 33 = 0
> with variables 1 << 32 = 1, 1 << 33 = 2
> $ gcc --version
> gcc (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2
Read the warning that was given to you!!
Shifting by greater-than-or-equal-to the width of the shifted type
is undefined behaviour, so your program could have printed anything.
What's actually happening to cause your specific output is probably
this:
When you use constants, the compiler is "smart" enough to realize
that you're shifting the bits right off the end, and so the result
is known at compile time to be zero. When the shift is variable
however,
the compiler emits actual shift instructions. A common low-level
implementation of a shift, down at the CPU level, actually masks out
anything beyond the 5 bits required to give you a 31-bit shift.
So if the shift value is 32, you actually get a shift of zero;
if it's 33, you get a shift of 1.
Again however, the code you wrote has undefined behaviour, so anything
can happen. In particular, in this case the output will almost
certainly be very dependent upon optimization levels, and perhaps
other "meaningless" changes such as whether a or b are declared
const (that last bit is just a wild guess, but entirely possible).