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