I try to make use of a left shift to identify a setbit using a counter. When I try to left shift var, I found that it is stuck in an infinite loop and only zero gets printed. What is wrong with the following code? Is it even legitimate to make use of a left shift inside a while loop?
#include <stdio.h>
#include <limits.h>
int main(int argc, char **argv)
{
int var =1;
while(var<INT_MAX)
{
var = var<<1;
printf("%d\n", var);
}
return 0;
}
It perfectly fine to use a shift operation inside a loop.
The problem with your code is that var
will never be equal or greater as INT_MAX
.
For better understanding let me explain the problem on an 8 bit signed interger and not on a 32 bit signed integer.
You start with the value var = 00000001b
(the b
indicates that it is a binary number) and the INT_MAX
for a 8 bit signed integer would be INT_MAX = 01111111b = 127
(notice that the highest bit is 0, this is because it is the sign bit)
Now if you left shift var
you are shifting this single 1 slowly to the right
var << 1 = 00000010b = 2
var << 2 = 00000100b = 4
var << 3 = 00001000b = 8
var << 4 = 00010000b = 16
var << 5 = 00100000b = 32
var << 6 = 01000000b = 64
var << 7 = 10000000b = -128
var << 8 = 00000000b = 0
var << 9 = 00000000b = 0
...
After the seventh shift the 1 bit reached the highest bit, but since we have an 8 bit signed integer we interprete 10000000b
not as 128
but as -128
and so var < INT_MAX
will always be true.
If you don't know why this happens you may want to read on two complement numbers.
Edit:
More formally, like Andrew Henle pointed out: shifting an value outside the range of its type is not defined.
The result ot the operation x << y
must be equal to x * 2^y
and if x * 2 ^y
is not representable with the type the result is not defined.
So the table from above looks more like
var << 1 = 00000010b = 2
var << 2 = 00000100b = 4
var << 3 = 00001000b = 8
var << 4 = 00010000b = 16
var << 5 = 00100000b = 32
var << 6 = 01000000b = 64
var << 7 = undef. = undef.
var << 8 = undef. = undef.
var << 9 = undef. = undef.
...