Be cautious when iterating bit-shifts

G

geo

#include <stdio.h>
int main()
{ int x=2048;
printf("%d\n",x);
printf("%d\n",((x<<2)>>2) );
printf("%d\n", (x<<2)>>2 );
printf("%d\n",((x<<2)>>2)-x );
printf("%d\n", (x<<2)>>2 -x );
}

Can you predict what five integers
will result from compiling and running
the above program?
Will all compilers give the same results?
 
N

Noob

geo said:
#include <stdio.h>
int main()
{ int x=2048;
printf("%d\n",x);
printf("%d\n",((x<<2)>>2) );
printf("%d\n", (x<<2)>>2 );
printf("%d\n",((x<<2)>>2)-x );
printf("%d\n", (x<<2)>>2 -x );
}

Can you predict what five integers
will result from compiling and running
the above program?
Will all compilers give the same results?

$ cat foo.c
#include <stdio.h>
int main(void)
{
int x=2048;
printf("%d\n",x);
printf("%d\n",((x<<2)>>2) );
printf("%d\n", (x<<2)>>2 );
printf("%d\n",((x<<2)>>2)-x );
printf("%d\n", (x<<2)>>2 -x );
return 0;
}

$ gcc -std=c89 -pedantic -Wall -Wextra foo.c
foo.c: In function 'main':
foo.c:9: warning: suggest parentheses around + or - inside shift

===> NB gcc's suggestion <===

$ ./a.out
2048
2048
2048
0
2048

INT_MAX must be at least 32767.
2048 << 2 equals 8192, thus x << 2 is always well-defined.
Let y = x << 2

You're considering
1. (y >> 2)
2. y >> 2
3. (y >> 2) - x
4. y >> 2 - x

1. and 2. are obviously equivalent, and equal to x.
3. is equivalent to x - x i.e. 0.
4. is equivalent to y >> (2-x) which is undefined.

Regards.
 
E

Eric Sosman

geo said:
#include <stdio.h>
int main()
{ int x=2048;
printf("%d\n",x);
printf("%d\n",((x<<2)>>2) );
printf("%d\n", (x<<2)>>2 );
printf("%d\n",((x<<2)>>2)-x );
printf("%d\n", (x<<2)>>2 -x );
}

Can you predict what five integers
will result from compiling and running
the above program?

No: Undefined behavior is not predictable. Not on the
basis of the C language, at any rate, although it might be
possible to predict the outcome for a given implementation.
Will all compilers give the same results?

Unlikely: Undefined behavior is not guaranteed to be
consistent.
 
P

Phil Carmody

geo said:
printf("%d\n",((x<<2)>>2)-x );

Don't mix bit-wise operations with arithmetic operations
unless you have an over-riding need to.

<< >> & | ^: fine
* / % + - : fine

Cross-pollination leads to mutants.

Phil
 
P

Phil Carmody

Richard Heathfield said:
Got me. I put my head on my left shoulder, trying to work out what
kind of smileys they were.


And thus to fitter life-forms. Analogies can be dangerous! :)

Absolutely, "(1u<<n)-1" has great longevity for a reason.

Phil
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top