[net.lang] Unchecked conversion in Ada & casts in C

throopw@rtp47.UUCP (Wayne Throop) (06/23/85)

The C notion of "cast" and the Ada notion of "unchecked conversion" (at
least the way I read K&R & the ANSI Ada standard) are not really
related, but a question about casts of pointers raised by Stavros
Mcrakis leads me to respond.

> > C casts are not bit-for-bit conversions unless the conversion happens
> > to be implemented as such...
>
> I would put it differently: C casts ARE bit-for-bit conversions except
> sometimes for numerical types.  To the extent that one can speak of C
> having any semantics at all, this makes the semantics of C casts grossly
> inconsistent.  For instance, (int) 2.3 == 2, but (*var=2.3, *((int *)
> var) ) == garbage; I don't even want to begin to think about the
> semantics of conversions involving unsigned's.

Close, but not quite right.  From page 42 of K&R:

    In the construction
        (type-name) expression
    the expression is converted to the named type by the conversion
    rules above.

where "the conversion rules above" went to great lenghts to detail
conversions done when when various arithmetic operators are fed
"mismatched" operands (including some of the messy unsigned cases).  K&R
then proceeded to use casts only when dealing with pointers in most of
the book.  Nowhere is it stated explicitly what conversions are done
with pointers, and this is the main point I want to raise, below.

> I also don't understand what `happens to be implemented as' means.  What
> other possibilities are there for converting pointers to integers,
> incompatible pointers, etc.?

"Happens to be implemented" is just the right phrase, it seems to me.
Conceptually, a cast is a production of a *new value*, not just looking
at a bucket of bits through given-type colored glasses.

But here is the main point, about casts of pointers.  K&R strongly imply
that casts of pointers deal with alignment problems.  That is, given a
machine where (say) 16-bit integers must be instantiated in storage with
address aligned mod 16 bits, and 8-bit characters must instantiated in
storage with address aligned mod 8 bits, the cast "(char *) int_ptr"
might pass the bits thru unchanged, but "(int *) char_ptr" would be free
to align the pointer value mod 16 bits.

The above covers a covers a use for casts between incompatible pointer
types.  There is also a use for a non-nop transform for pointers to
integers (and vice versa).  On a machine where 8-bit-granular pointers
have a *different bit-wise representation* than 16-bit-granular
pointers, K&R implies that it is up to the user to be careful when
assigning pointers to integers and then back to pointers to be sure that
the pointer types involved are the same type.  Unfortunately, almost no
current C programs follow this K&R compatible discipline.  Therefore, to
support those (strictly speaking, incorrect) programs, a compiler might
(and I know of a compiler that does) always convert 16-bit granular
pointer format to 8-bit granular format when the pointer is cast to or
stored in an integer.

> So perhaps it was a bad idea to compare Unchecked_conversion in Ada to C
> casts.  I just wanted to use a reference point familiar to C users.

I wouldn't exactly call it a bad idea, since even though the concepts
are not *closely* related they *are* related.  However, I'd say that
Ada's notion of unchecked conversion is more closely related to (the
nonportable) use of C's union types to view memory using a variety of
type interpretations.  It might have been better to use that analogy.

[As an aside, I think that all pointer formats should be 1-bit-granular
 to get rid of such things as pointer-format nonsense but that belongs
 in another newsgroup, net.arch]

[Another aside.  The original thread of this conversation (I think) was
 "Who needs Ada?".  Well, *I* need Ada (or *some* strongly typechecked
 language) so that I don't have to worry about stuff like pointer
 formats and what happens to them when they are abused.  I druther the
 compiler didn't let me abuse them in the first place.  That is, the
 compiler should *not let* pointers be assigned to integers, except via
 unions or explicit unchecked conversion.  But I suppose that belongs in
 net.religion.]

[Sorry this article is so long.  I didn't have time to make it shorter.
 Can you say "long-winded"?  Can you say "overkill"?  I knew you could.]
-- 
Wayne Throop at Data General, RTP, NC
<the-known-world>!mcnc!rti-sel!rtp47!throopw

david@ukma.UUCP (David Herron, NPR Lover) (06/25/85)

In article <74@rtp47.UUCP> throopw@rtp47.UUCP (Wayne Throop) writes:
> ...
>But here is the main point, about casts of pointers.  K&R strongly imply
>that casts of pointers deal with alignment problems.  That is, given a
>machine where (say) 16-bit integers must be instantiated in storage with
>address aligned mod 16 bits, and 8-bit characters must instantiated in
>storage with address aligned mod 8 bits, the cast "(char *) int_ptr"
>might pass the bits thru unchanged, but "(int *) char_ptr" would be free
>to align the pointer value mod 16 bits.

This is why (when I'm coding) I make extensive use of casts, etc. 
Especially when I'm the least big sure of how the types will mix.

Generally, I feel that it's the programmers duty to give the compiler
*as much* information as possible.  That is the only way the compiler
will be able to make any informed intelligent decisions about what
code to generate.  And if it still doesn't come out right then you can
point fingers at the compiler writer and shout "LAZY!".

This is certainly the way the C standard is heading.  At least in the
draft as of last October, it mainly consisted of strict definitions
of what all the operators did.  But also general enough that it wasn't
tied very closely to a PDP-11 type architecture.  (I have April's draft
but haven't looked at it yet).  But with such a definition (and compilers
that follow it) a programmer can confidently write expressions and know
that the compiler knows enough about the machine to know what conversions
he has in mind.

What's wrong with giving the compiler a lot of intelligence?  Teaching
it what all the conversions mean.  And so forth.  Then when you have
your intelligent compiler, the programmer can make use of the intelligence
to have more confidence in their code.

At least that is the ideal.

>[Another aside.  The original thread of this conversation (I think) was
> "Who needs Ada?".  Well, *I* need Ada (or *some* strongly typechecked
> language) so that I don't have to worry about stuff like pointer
> formats and what happens to them when they are abused.  I druther the
> compiler didn't let me abuse them in the first place.  That is, the
> compiler should *not let* pointers be assigned to integers, except via
> unions or explicit unchecked conversion.  But I suppose that belongs in
> net.religion.]

I prefer to describe in detail what I want to do.  But I also find assembly
language cumbersome (It takes too many lines of code to describe a simple
expression).  It's like the reason I drive a standard shift, I like having
control of my tools.
-- 
--- David Herron
--- ARPA-> ukma!david@ANL-MCS.ARPA or ukma!david<@ANL-MCS> 
---	   or david%ukma.uucp@anl-mcs.arpa
---        Or even anlams!ukma!david@ucbvax.arpa
--- UUCP-> {ucbvax,unmvax,boulder,oddjob}!anlams!ukma!david
---        {ihnp4,decvax,ucbvax}!cbosgd!ukma!david

	"It's *Super*User* to the rescue!"