C11 adds, among other things, 'Anonymous Structs and Unions'.
I poked around but could not find a clear explanation of when anonymous structs and unions would be useful. I ask because I don't completely understand what they are. I get that they are structs or unions without the name afterwards, but I have always (had to?) treat that as an error so I can only conceive a use for named structs.
In C11 standard of C, anonymous Unions and structures were added. Anonymous unions/structures are also known as unnamed unions/structures as they don't have names. Since there is no names, direct objects(or variables) of them are not created and we use them in nested structure or unions.
An anonymous union is a union without a name. It cannot be followed by a declarator. An anonymous union is not a type; it defines an unnamed object. The member names of an anonymous union must be distinct from other names within the scope in which the union is declared.
The anonymous unions and structures are unnamed unions and structures. As they have no names, so we cannot create direct objects of it. We use it as nested structures or unions. These are the examples of anonymous union and structures.
Anonymous union inside structures are very useful in practice. Consider that you want to implement a discriminated sum type (or tagged union), an aggregate with a boolean and either a float or a char*
(i.e. a string), depending upon the boolean flag. With C11 you should be able to code
typedef struct { bool is_float; union { float f; char* s; }; } mychoice_t; double as_float(mychoice_t* ch) { if (ch->is_float) return ch->f; else return atof(ch->s); }
With C99, you'll have to name the union, and code ch->u.f
and ch->u.s
which is less readable and more verbose.
Another way to implement some tagged union type is to use casts. The Ocaml runtime gives a lot of examples.
The SBCL implementation of Common Lisp does use some union
to implement tagged union types. And GNU make also uses them.
A typical and real world use of anonymous structs and unions are to provide an alternative view to data. For example when implementing a 3D point type:
typedef struct { union{ struct{ double x; double y; double z; }; double raw[3]; }; }vec3d_t; vec3d_t v; v.x = 4.0; v.raw[1] = 3.0; // Equivalent to v.y = 3.0 v.z = 2.0;
This is useful if you interface to code that expects a 3D vector as a pointer to three doubles. Instead of doing f(&v.x)
which is ugly, you can do f(v.raw)
which makes your intent clear.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With