kozak@grad2.cis.upenn.edu (Chuck Kozak) (10/21/90)
I have seen code where the first N members of different structures are accessed by code that treats the structures as identical. I looked through K&R II to check whether this practice is legal and cannot find any mention of it. This practice works with GNU C on a SUN-4 and I cannot think of a reason why it would not work on other architectures, but I would like to know whether it is a safe or bad practice. An example of what I mean is given below. struct common { struct common *next; struct common *prev; int type; }; struct type_1 { struct common *next; struct common *prev; int type; ... type_1 specific members ... }; struct type_2 { struct common *next; struct common *prev; int type; ... type_2 specific members ... }; void common_function(struct common *pnt) { ... access the next, prev, and type members ... } ... other code ... struct type_1 type_1_data; common_function((struct common *) &type_1_data); ... thanks for your help, Chuck Kozak kozak@grad2.cis.upenn.edu
henry@zoo.toronto.edu (Henry Spencer) (10/21/90)
In article <31468@netnews.upenn.edu> kozak@grad1.cis.upenn.edu (Chuck Kozak) writes: >I have seen code where the first N members of different structures >are accessed by code that treats the structures as identical. I >looked through K&R II to check whether this practice is legal and >cannot find any mention of it... ANSI C promises that this will work only when all the structures in question are within a union. (Sufficiently determined theological reasoning might possibly demonstrate that this suffices to guarantee it everywhere.) It is dubious practice at best. -- The type syntax for C is essentially | Henry Spencer at U of Toronto Zoology unparsable. --Rob Pike | henry@zoo.toronto.edu utzoo!henry
richard@aiai.ed.ac.uk (Richard Tobin) (10/23/90)
In article <1990Oct21.051028.11018@zoo.toronto.edu> henry@zoo.toronto.edu (Henry Spencer) writes: > It is dubious practice at best. This technique is often used where an object may be of several different kinds, with a type field to distinguish them. For example: enum type {number, cons}; struct number {enum type type; int value;}; struct cons {enum type type; union obj *car, *cdr;}; union obj {struct number; struct cons;}; An alternative, of course, is to do it like this: struct number {double value;}; struct cons {struct obj *car, *cdr;}; struct obj {enum type type; union {struct cons cons; struct number number;} value;}; But if you want to allocate only the necessary amount of space when creating a "number" object, the first form is simpler (you allocate sizeof(struct number) and cast its address to a (union obj *), whereas with the second form I think you would have to use something like offsetof(struct obj, value) + sizeof(struct number)). I would be interested to hear of elegant, portable ways to do this. -- Richard -- Richard Tobin, JANET: R.Tobin@uk.ac.ed AI Applications Institute, ARPA: R.Tobin%uk.ac.ed@nsfnet-relay.ac.uk Edinburgh University. UUCP: ...!ukc!ed.ac.uk!R.Tobin