David said:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This is usenet. You'll be corrected even if when you're not wrong.
True, as you proceed to demonstrate
But, if you look again, you'll see that 1 isn't being left-shifted by
the number of bits in an int:
for(
counter=(sizeof(int)*8);
counter>=0;
--counter
)
While counter is initialised as the number of bits in an int, I
specifically used --counter to pre-decrement it before passing through
the loop. In other words, it starts with 1 being left-shifted by one
less than the number of bits in an int.
The code snipped in full, with added commentary by me was
printf("\nBinary: ");
for(counter=(sizeof(int)*8);counter>=0;--counter)
{
/* First time though counter will be (sizeof(int)*8) since the --counter
expression is not executed until *after* the first execution of the loop */
temp = 1 << (counter);
/* So the above statement invokes undefined behaviour */
printf("%d", (number & temp) ? 1 : 0);
}
<aside>
I seem to remember a recent thread here about the merits of pre/post
increment when used like this and someone suggesting the pre-increment
could be miss-interpreted in exactly the way David Bolt has just done.
David has just proved that hypothesis, although I would personally use
that as an argument for David to learn more rather than to avoid the
pre-increment. I prefer the post increment, but as a matter of style
rather than belief that it is in some manner better.
</aside>
By the way, even if you "correct" it to:
printf("\nBinary: ");
for(counter=(sizeof(int)*8)-1;counter>=0;--counter)
{
temp = 1 << (counter);
printf("%d", (number & temp) ? 1 : 0);
}
You can still invoke undefined behaviour. To quote from N1124 section
6.5.7 para 4:
| The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated
| bits are filled with zeros. If E1 has an unsigned type, the value of
| the result is E1 * 2**E2, reduced modulo one more than the maximum
| value representable in the result type. If E1 has a signed type and
| nonnegative value, and E1 × 2**E2 is representable in the result type,
| then that is the resulting value; otherwise, the behavior is
| undefined.
I've used ** to represent "raising to the power" since superscript is
not easy to do.
Read the last sentence and you will see that trying to shift a 1 in to
the sign bit of a signed number (and 1 is a signed int) is explicitly
undefined behaviour.
Generally you should make sure you are using unsigned types when using
bit operators to avoid this kind of trap, and that includes specifying
constants as unsigned.