On Fri, May 19, 2006 at 09:08:06PM -0600, Hans Fugal wrote:
> On Fri, 19 May 2006 at 17:13 -0600, Michael L Torrie wrote:
> > Is this not a bad thing?  I definitely wouldn't want a number I'm
> > shifting to be casted to an int as that can change the meaning of the
> > shift.  
> > 
> > But Java doesn't have unsigned numbers, right?
> > 
> > I'll add that to my list of reasons to dislike Java.
> 
> Well that's what C does.
> 
> 
>     int main(void)
>     {
>         printf("%x %x\n",
>                ((unsigned char)0xff) << 8,
>                ((char)0xff) << 8);
>     }
> 
> produces
> 
>     ff00 ffffff00
> 
> Neither of which is a char, unsigned or no.

Another way to look at it:

unsigned char c = (unsigned char)0xff << (unsigned char)8;

really means

unsigned char c = (unsigned char)((int)(unsigned char)(0xff) <<
(int)(unsigned char)8);

The extra cast (truncate) back to unsigned char only happens because of
the assignment to a variable of type unsigned char.

See sections 6.3.1.1 and 6.3.1.8 of the ISO/IEC 9899
(the C99 standard) for an explanation of integer promotions and their
applicability to arithmetic operations.

The compiler can shortcut this if it can be guaranteed that the result
will be the same as shifting an int by an int and then truncating to
unsigned char.  

In the case of the printf example above, char (unsigned or not)
arguments to variadic functions are passed as int.  See section 6.5.2.2
or the C99 standard.  The format string "%x" interprets these promoted
arguments as an unsigned int, so that's what gets printed.  The unsigned
int created because integer promotions were performed on the shift
operands.

Note: if the section numbers for the C99 standard are off it's because I
referenced the most recent draft version.

-- 
Byron Clark

Attachment: signature.asc
Description: Digital signature

/*
PLUG: http://plug.org, #utah on irc.freenode.net
Unsubscribe: http://plug.org/mailman/options/plug
Don't fear the penguin.
*/

Reply via email to