I have been making some stupid test about bits manipulation, and I found this issue. I execute this code:
int main(){
unsigned int i;
for (i=1; i<34; i++)
{
unsigned long temp = i;
unsigned long mul = 1;
unsigned long val;
unsigned long one = 1;
// Way 1
while (temp--)
mul = mul << one;
// Way 2
val = (one<<i);
printf(" \n 1<<%i \n mul: 0x%X , val: 0x%X\n",i, mul, val);
}
}
Of course, I know that when i>31, an overflow will be produced. I think that both parts of code (way1 and way2) should output the same result. But I get this (at the end):
/* ... correct results from i=1 to i=31 ... */
1<<30
mul: 0x40000000 , val: 0x40000000
1<<31
mul: 0x80000000 , val: 0x80000000
1<<32
mul: **0x0** , val: **0x1**
1<<33
mul: **0x0** , val: **0x2**
Why, if both instructions are left shifts, the program produces different outputs? It seems that the part way2 produces a round shift, but I don't know why, I really think that "mul" gets always the correct value.
I compile under a Intel 32bits machine, gcc version 4.4.7
Probably because that's undefined behaviour? According to §6.5.7
:
If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined.
In case of
val = (one<<i);
when i
gets greater than or equal to 32, the behavior is undefined.
However, in case of
while (temp--)
mul = mul << one;
for shifts more than 32, it will shift zero and the result is defined (zero).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With