C union problems (or is a pointer a pointer?)

Bill Sears bills at sequent.UUCP
Wed Apr 26 04:44:06 AEST 1989


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?



More information about the Comp.lang.c mailing list