Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!tut.cis.ohio-state.edu!cs.utexas.edu!uunet!tektronix!sequent!bills From: bills@sequent.UUCP (Bill Sears) Newsgroups: comp.lang.c Subject: C union problems (or is a pointer a pointer?) Keywords: C, Pascal, pointer, union, variant Message-ID: <15058@sequent.UUCP> Date: 25 Apr 89 18:44:06 GMT Reply-To: bills@sequent.UUCP (Bill Sears) Organization: Sequent Computer Systems, Inc Lines: 87 What this posting basically boils down to is: Is a pointer a pointer? In other words if I have a pointer to a given object, can I typecast it into a pointer to another object and be guaranteed that the new pointer will be "the same" as the old pointer? The scenario is fairly long. Please ignore the errors caused by omission. Consider the following scenario. I have a list of structures which have three fields: a char array, a type, and a pointer which points to one of two objects depending upon the aforementioned type. typedef enum { ismenu, isaction } objtype; typedef struct { char desc[40]; objtype stype; union { MENU *menu; ACTION *action; } dummy; } SELECTION; SELECTION a; The problem with this is that in order to declare a union, you must introduce a new variable into the structure (i.e. dummy). Now my two pointers must be accessed as "a.dummy.menu" and "a.dummy.action", rather than (the preferable) "a.menu" and "a.action". One way to solve this is not to use a union. typedef struct { char desc[40]; objtype stype; MENU *menu; ACTION *action; } SELECTION; This results in unused storage being allocated for each SELECTION. Another solution is to use a single pointer variable to reference both possibilities. typedef struct { char desc[40]; objtype stype; char *objptr; /* or int * or long * */ } SELECTION; Now, by casting objptr to be the type of pointer that I am using at any given time, I can get rid of any compile errors, but is this always guaranteed to work? In other words, is a pointer a pointer? Although this is probably a matter of personal taste and programming style, which of the above implementations is the "most desirable"? They all have flaws (as I have documented) but which is the "best". For no particular reason, other than information, the following is the Pascal code which will implement this same scenario. Since I am not a Pascal programmer, please ignore errors in this fragment. I think it is correct enough to convey the desired idea. type objtype = (ismenu, isaction); act_ptr = ^action; menu_ptr = ^menu; selection = record desc : packed array[1..40] of char; case stype : objtype of ismenu : ( menu : menu_ptr ); isaction : ( action : act_ptr ) end; var a : selection; This solves all of the above flaws, but introduces one of it's own (i.e. it's in the wrong language :-). The pointer fields are accessed via "a.menu" and "a.action", there is no wasted space introduced, and all of the pointer types will point to their own type of structure. Was the Pascal variant record syntax designed to overcome the above restrictions with the C union, or is it just coincidental that it does? Any comments?