[comp.lang.c] Type conversion within arithmetic expressions. What does ANSI say ?

elee24@castle.ed.ac.uk (H Bruce) (10/04/90)

How should the following code fragment compile ?

unsigned char x,y;
unsigned short int z;
z=x*y;

According to the ANSI standard, if the result of x*y exceeds 255, 
will all 16 bits be copied to z  or only the lower 8 ?
(i.e if x=2 and y=200 does z=400 or 400%256 ?)

I have a C compiler for the 8051 which does not copy the upper byte across
even if z=x*y is replaced with z=(unsigned short int)x*y.
I want to confirm that this is a bug.
Microsoft C does convert the result into 16 bits without a type cast.

I can't find reference to this in any "ANSI" C books that we have.


Thanks,

Henry Bruce.

jh4o+@andrew.cmu.edu (Jeffrey T. Hutzelman) (10/05/90)

The ANSI standard does not guarantee the sizes of unsigned char and
unsigned short int; only that sizeof(char)<=sizeof(short).  If you
want to be sure it works, try z=(unsigned short)x * (unsigned short)y
(you may need parens; I'm not familiar with the precedence rules
regarding type casting, but I think it is higher that multiply).
-----------------
Jeffrey Hutzelman
America Online: JeffreyH11
Internet/BITNET:jh4o+@andrew.cmu.edu, jhutz@drycas.club.cc.cmu.edu

>> Apple // Forever!!! <<

henry@zoo.toronto.edu (Henry Spencer) (10/06/90)

In article <6584@castle.ed.ac.uk> elee24@castle.ed.ac.uk (H Bruce) writes:
>How should the following code fragment compile ?
>
>unsigned char x,y;
>unsigned short int z;
>z=x*y;
>
>According to the ANSI standard, if the result of x*y exceeds 255, 
>will all 16 bits be copied to z  or only the lower 8 ?
>(i.e if x=2 and y=200 does z=400 or 400%256 ?)
>
>I have a C compiler for the 8051 which does not copy the upper byte across
>even if z=x*y is replaced with z=(unsigned short int)x*y.

The first question you should ask is "how big is `unsigned short' on the
8051?".  If it's 8 bits, then your question is answered.  This would not
be an ANSI-standard implementation, since ANSI C requires >=16 bits for
shorts of all kinds, but there are lots of non-ANSI and semi-ANSI compilers
out there, especially for cruddy little 8-bit machines that have trouble
supporting 16-bit and 32-bit arithmetic efficiently.

Assuming that `unsigned short' is indeed 16 bits, your compiler is exceeding
its authority here.  `unsigned char' turns into some sort of `int' (details
slightly implementation-dependent) immediately on use in an expression, so
the value of that multiplication is definitely at least 16 bits, and should
be copied as such.  A compiler can shorten such operations only if it can
guarantee that this will not affect results... not true in this case.
-- 
Imagine life with OS/360 the standard  | Henry Spencer at U of Toronto Zoology
operating system.  Now think about X.  |  henry@zoo.toronto.edu   utzoo!henry