[comp.lang.c] Implicit and explicit casts...

chris@mimsy.UUCP (Chris Torek) (10/17/88)

In article <8810111925.AA21750@ucbarpa.Berkeley.EDU> U23405@UICVM.Berkeley.EDU
(Michael J. Steiner) writes:
>Since type conversions take place across the assignment operator, I would think
>that the compiler would put in the appropriate casts if one wasn't specified.
>Also, sometimes a cast will convert data types successfully whereas mere
>assignment won't. What is the difference between the two? Does K&R say
>anything about this?

K&R (1st ed.) is vague about the difference, but every `natural'
conversion will happen across an assignment, and only pointer
conversions require casts here.  This includes pointer-to-integral,
integral-to-pointer, and pointer-to-T1 to pointer-to-T2 wherever T1 and
T2 are distinct types.  Structure and union conversions are illegal
whether cast or not.

In other words, an explicit cast is only required when one or more of
the following hold:

   - there is no implicit cast
   - the implicit cast would cause at least a warning
   - the explicit cast is to a different type than the implicit cast
     (in which case the explicit cast is followed by the implicit cast)

The last case is something like

	short s;
	int i;
	i = (unsigned char)s;

which moves the value in `s' through four(!) types before reaching
`int' and storing in `i':

	what				type
	----				----
	s				short, lvalue
	<sign extended value>s		int, rvalue
	<truncated value>s		unsigned char, rvalue
	<expanded truncated value>s	unsigned int, rvalue

The last type may be (but is not necessarily) different under the dpANS
C `value preserving' rules:  (unsigned char) expands to (signed int),
unless the number of bits in an unsigned char is greater than or equal
to the number of bits in a signed int.  Since the number of bits in a
char (signed or not) may not be greater, the type is either (signed int)
or (unsigned int) depending on whether sizeof(char)==sizeof(int).
This is conceptually grotesque, but makes little difference in practise.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

bill@twwells.uucp (T. William Wells) (10/20/88)

In article <14028@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes:
:       short s;
:       int i;
:       i = (unsigned char)s;
:
: which moves the value in `s' through four(!) types before reaching
: `int' and storing in `i':
:
:       what                            type
:       ----                            ----
:       s                               short, lvalue
:       <sign extended value>s          int, rvalue
:       <truncated value>s              unsigned char, rvalue
:       <expanded truncated value>s     unsigned int, rvalue

I understand that there are some compilers that do not do the
truncation properly. In other words,

	int     i = (unsigned char)0xFFFF;

stores 0xFFFF in i, instead of 0xFF (assuming 8 bit bytes, of course).

Such compilers are broken, but if portability is a concern, one
should avoid assuming that casting (or for that matter, assigning to
a char) properly truncates a value.

---
Bill
novavax!proxftl!twwells!bill