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?
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.
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.
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.
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.
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;
};