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.eduhenry@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