Path: utzoo!utgpu!water!watmath!clyde!att!osu-cis!tut.cis.ohio-state.edu!mailrus!ames!ncar!oddjob!mimsy!chris From: chris@mimsy.UUCP (Chris Torek) Newsgroups: comp.lang.c Subject: Re: Union type conversions Message-ID: <12789@mimsy.UUCP> Date: 2 Aug 88 05:35:40 GMT References: <224.22F29448@stjhmc.fidonet.org> Organization: U of Maryland, Dept. of Computer Science, Coll. Pk., MD 20742 Lines: 103 In some article whose referent was deleted by deficient news software (actually, by crossing a news/FIDO gateway), I wrote in re union offsets: >>Write some correct code that produces a wrong answer if a union of a >>set of elements were implemented as a structure containing all the >>elements, and you will have a proof. (Incidentally, you need to do this for all possible cases to make a proof for more than just one case. This was in an article in which my point was `in a computer language, a difference that makes no difference *is* no difference.') In article <224.22F29448@stjhmc.fidonet.org> will.summers@p6.f18.n114.z1.fidonet.org (will summers) writes: >How about: > union { int a; int b; } x; > > int offset_of_b = (int) (&x.b - &x); > ... > > if (offset_of_b != 0) > printf("compiler is broke\n"); >So what's wrong with the above code? `Let me count the ways ...' :-) First: you have subtracted pointers of different types; that operation is undefined. Well, we could fix that: int offset_of_b = &x.b - &x.a; but it may still be wrong to assume that offset_of_b should then be 0. >"A union may be thought of as a structure all of whose members begin at >offset 0" (K&R A.8.5, pg 197). > >If I may "think of" a union as an "all 0 offset structure", then I may write >code that fails when any aspect of that metaphor is violated. You may indeed---but it might still be incorrect code. The question here is really in regard to the original wording: why say `may be thought of as' rather than `is'? Given that this is in a tutorial, rather than a formal language definition, there is one very likely answer: perhaps `is' would be false. After all, a float `may be thought of as' a pair of integers separated by a decimal point. That metaphor works to a fair extent, but it breaks down when you really push it. Perhaps the same is true of a union. Just possibly, the idea was that a union would be a structure with zero offsets, except wherever that happened not to be ideal, such as when embedded into another structure: struct this_could_be_aligned_fancily { char name[7]; /* object name, max 7 letters */ union { long l; /* value if long */ char c[5]; /* value if string */ } u; /* (type distinguished by name) */ }; On a byte-addressible machine where `long's must be aligned at a multiple of four bytes (e.g., SPARC), the obvious way to pack this is: offset object(s) ------ --------- 0 name[0] 1 name[1] ... 6 name[6] 7 8 u.l, u.c[0] 9 u.l, u.c[1] 10 u.l, u.c[2] 11 u.l, u.c[3] 12 u.c[4] 13 14 15 A `better' way to pack it is this: offset object(s) ------ --------- 0 name[0] ... 6 name[6] 7 u.c[0] 8 u.l, u.c[1] 9 u.l, u.c[2] 10 u.l, u.c[3] 11 u.l, u.c[4] This saves four bytes per structure object. The question, then, is `is such a packing legal?' K&R does not really answer this. I hope that the dpANS does, and does so with a `no'; but I do not know whether this is in fact the case. (I had hoped not to have to be this explicit, but at least this is better than reruns of `pointers vs. arrays' or `defining NULL' :-) .) -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris