casting structures

throopw at dg_rtp.UUCP throopw at dg_rtp.UUCP
Wed Feb 19 10:04:13 AEST 1986


I'd like to correct a misleading and mistaken example posted in  message
<392 at ccivax.UUCP>.   You may consider this a flamage warning.

>>Are there any other cases where casts are NEEDED besides:
>>              [some cases]

In message <392 at ccivax.UUCP> <rb at ccivax.UUCP (rex ballard)> says:
>	Yes, accessing members of structures.
>	ie:
>	struct x y;
>	struct i j;
>	i.memb=y.memb;  /* some compilers hate this */
>	should be written:
>	i.memb= ((struct i)x).memb;
>
>	this is especially true if both structures contain 'memb' but
>	'memb' is different type or placement.
>	A union is probably preferred.

Where to begin?  Well, let's start out by pointing out that the 'i' in
'i.memb' must be a 'j' (both places), and the 'x' in '(struct i)x' must
be a 'y'. I can't think of any reasonable way of making this fragment
into a legal C program otherwise. Next, the definitions of 'memb' are
missing, so I'm not sure what is meant by "different type or placement".
Let's assume he means something like the following somewhat more
complete example:

        struct s1 {int a; char b;};
        struct s2 {char b; int a;};

        void f(){
            struct s1 x1;
            struct s2 x2;

            x1.a = x2.a;
            x1.a = ((struct s1)x2).a;
        }

Ok, now with a complete example in hand, let's see what's what.  To
start with, Harbison and Steele says (sec 6.5, pg 129, chant along if
you have the hymnal folks)

    An object of a structure or union type *T* may be converted only to
    a type that is the same as *T* (the trivial conversion).  There is
    no change of representation, except that the bit patterns in any
    unused "holes" in the structure or union are not necessarily
    preserved.

Amen.  From this I predict that any adequate typechecker will get sick
all over my complete example, and I am not let down by my favorite one.
It points out the cast as illegal, and raises not a peep over the
uncasted assignment that Rex claims might not work.

I will even stick my neck out further and assert that any compiler which
does not accept the uncasted expression is not a compiler for the C
language.  But what will a compiler do with the cast (as opposed to a
typechecker, which had better complain)?  Well, my handy-dandy "You
Asked For It, You Got It" C compiler allocates the structs like so:

            |       |       |       |       |       |       |
    s1:     |int a;     (32 bits)           |char b;|padding|
    s2:     |char b;|padding|int a;    (32 bits)            |
            |       |       |       |       |       |       |

For x1.a = x2.a, the compiler moves the 32 bits of integer in the s2
shaped record to the 32 bits of integer in the s1 shaped record.  For
the casted abomination, (got your barf bags ready?) it moves the 8 bits
of b, plus the 8 bits of padding, plus the first 16 bits of a in the s2
shaped structure, and places them in the 32 bits of a in the s1 shaped
structure.  (Trust me.  That's what it does.  I tried it out.)

Somehow I think that maybe (just maybe) Rex hasn't actually used his
handy-dandy coding tip in any working program... what do y'all think?

(Unless of course the posting was a joke, in which case I'd merely say
 that it was a moderately dangerous and ill-conceived joke.)
-- 
Wayne Throop at Data General, RTP, NC
<the-known-world>!mcnc!rti-sel!dg_rtp!throopw



More information about the Comp.lang.c mailing list