tags:

views:

132

answers:

5

In C, is it possible to define a union within another union? If no, why is it not possible? Or if yes, where can it be used?

+1  A: 

Yes it is possible. But I'd tend to stick with the advice of never use unions. The number of situations where unions are the right answer are very small. I suspect there is no situation where a union containing a union is a good idea.

Nick Fortescue
Ack, you beat me with a few seconds. Ah well, +1 since that is almost exactly what I intended to post.
Christoffer
"...there is **no** situation..." Don't you know you should **never** use absolute statements like this? :)
semaj
@Nick: Nonsense. There are plenty of situations that require a union. In fact, C programmers tend not to use unions when they're the right answer (and use too many casts instead), so you should be advertising *for* their use.
Gilles
@Gilles: most uses of unions in place of pointer casts result in undefined behavior.
R..
@R..: You often do end up needing pointer casts in some places when unions are involved, but I don't see what you have in mind with this comment. Could you give an example of a situation where you've seen people use unions when they shouldn't have?
Gilles
The C standard says reading a member of a union other than the most-recently-written one results in undefined behavior. Period. On the other hand, behavior is defined if you access an object via a pointer to an overlapping array of `unsigned char` having the same size as the object. Any other pointer cast hacks result in undefined behavior.
R..
@semaj My background is as a mathematician, I don't make comments like this lightly. Hence the "I suspect". :-)
Nick Fortescue
@Gilles - I stand by my statement that they are very small. The fact that most newer languages chose to leave them out says that in the vast majority of cases they aren't needed. Of course there are situations where they are the best way to do things. It is a matter of opinion whether unions are better than pointer casts, I might even argue a union is just a specialised form of cast, and not much better.
Nick Fortescue
@R..: No, you missed a very important case: with unions of structs where the structs have a first field of the same type, you can read the first field through any component (N1256 §6.5.2.3.5). This is the basis for a common, standard-compliant, implementation of discriminated union in C. (However this dispensation does not extend to nested unions, the topic of this question, so [my example](http://stackoverflow.com/questions/3823380/unions-within-unions/3825089#3825089) was wrong (now fixed).)
Gilles
@Nick: Many object-oriented languages fail to provide a good form of unions, and it's something programmers have to work around. F# reverses the trend. Even within C's type system's very limited guarantees, unions do allow better type checking than casts. Of course, you have to provide your own discriminators.
Gilles
A: 

Yes, it is possible. I can't think of a good use of the top of my head, although it would be easy to come up with a contrived example.

Oli Charlesworth
A: 

Yes, a union may contain another union:

union foo {
  int x;
  double y;
  union bar {
    char blah[10];
    char *blurga;
  } bletch;
};

I can't think of a situation where it would be useful (or even desirable), though.

John Bode
+2  A: 

Suppose you want to define:

union myun {
  int x;
  sometype y;
};

where sometype is a typedef defined by a library you're using. If the library happened to implement it as a union type, then this would be a union within a union, and it would make sense because you can't (from a good design standpoint) violate the encapsulation of the library's type.

R..
Okay.. Got it..
Raj Kumar
That's not really true. You need to have the REAL type accessible to compile the code. It may not be direct (it may be a typedef of typedef of typedef...), but the source type must be accessible somewhere.
Let_Me_Be
+1  A: 

Yes, it's possible, and useful. The reason is the same reason X within Y is useful for many values of X and Y: compositionality. Programs are built by assembling tiny components into small components into larger components into huge components into... Sometimes a bunch of unions happen to be assembled into a union, and so what?

R..'s answer shows an example where this happens behind the scenes: it just happens that one of the union member types is a union, but you don't know that unless you look at the library implementation.


EDIT However, note that the common idiom for discriminated unions where each member of the union is a structure whose first field is an integral type containing a tag does not extend to nested unions. That is, the following is a common, standard-compliant (N1256 §6.5.2.3.5) implementation of discriminated unions in C:

struct generic {
    unsigned tag;
};
struct smallnum {
    unsigned tag; /*always TAG_SMALLNUM*/
    unsigned value;
};
struct bignum {
    unsigned tag; /*always TAG_BIGNUM*/
    size_t length;
    unsigned *p;
};
struct string {
    unsigned tag; /*always TAG_STRING*/
    size_t length;
    char *p;
};
union number {
    struct bignum bignum;
    struct smallnum smallnum;
};
union object {
    struct generic generic;
    struct bignum bignum;
    struct smallnum smallnum;
    struct string string;
};

If you have an union object object x, you can always read its tag as x.generic.tag (or x.bignum.tag or any of the others), no matter what was actually assigned to the object. By using unique tags (discriminators) for the objects.

The following definition is legal, but not useful as you cannot just read the first field of a union level2 object to get the tag: if a union level2 object was written as a union number, you have to read its tag through the number member, and otherwise you have to read its tag through the generic or string member. I wouldn't be surprised if accessing through the wrong member worked on every now existing implementation, but it is not standard-compliant.

union level2 {
    struct generic generic;
    union number number;
    struct string string;
};
Gilles