union or type casting, which to use?

Paul D. Smith pds at lemming.webo.dg.com
Wed Nov 28 10:02:41 AEST 1990


[] > One of the major need is to be able to statically initialize the
[] > `item' field. ...

[]   Hummm...  Now, after all of this, I'm not going to answer your
[]   real question.  I don't know if you can staticly initialize a
[]   union.  Sorry.  :-/

ANSI C defines that the first item in a union may be initialized, but
only the first item.  This is done by just initializing the fields of
the first element of the union just as if it was a structure, i.e.:

typedef union
{
    struct
    {
        int     u1_int;
        char    *u1_str;
    } u1;
    struct
    {
        char    u2_char;
        char    *u2_charp;
    } u2;
} MY_STRUCT;

Initialize with:

MY_STRUCT my_struct =
{                                   /* union MY_STRUCT */
    {                               /* struct u1 */
        5,                          /* u1_int */
        "blooper"                   /* u1_str */
    }
};

Note u2 cannot be initialized.  If you don't want your program to be
portable, it is sometimes possible with some foreknowledge of the
relative sizes, etc. of different data types to declare the first
element to be general enough to hold all the other elements, if they
are cast correctly.

[] > I want to create a new typedef with a field to hold a pointer to
[] > either `foo' or `bar'. Is there any pros/cons of using union vs.
[] > (explicit) type casting? For instance, is
[] > 
[] >   typedef struct {
[] >     int type; /* 0 for foo pointer, 1 for bar pointer */
[] >     union {
[] >       foo *f;
[] >       bar *b;
[] >     } item;
[] >   } oneof1;

In your case, you have no problem: the union elements are both the
same size and are guaranteed by ANSI to be compatible with a cast:
both are pointers.  You can simply in the static initialization cast
the pointer to be of type (foo *), like this:

foo *f_ptr;
bar *b_ptr;

oneof1 my_foo =
{
    0,                      /* type: foo pointer */
    {                       /* union item */
        f_ptr               /* f */
    }
};

oneof1 my_bar =
{
    1,                      /* type: bar pointer */
    {                       /* union item */
        (foo *)b_ptr        /* f */
    }
};

And all will work wonderfully!
--

                                                                paul
-----
 ------------------------------------------------------------------
| Paul D. Smith                          | pds at lemming.webo.dg.com |
| Data General Corp.                     |                         |
| Network Services Development Division  |   "Pretty Damn S..."    |
| Open Network Systems Development       |                         |
 ------------------------------------------------------------------



More information about the Comp.lang.c mailing list