I'm reading some code and found something like the following:
typedef union {
int int32;
int boolean;
time_t date;
char *string;
union {
struct foo *a;
struct foo *b;
struct foo *c;
};
} type_t;
From syntax point of view, the inner union {} can be removed and having *a, *b and *c directly inside the outer union {}. So what's the purpose the namelessly embedded union?
Unnamed union/struct inside another union/struct is a feature of C11, and some compiler extensions (e.g, GCC).
C11 §6.7.2.1 Structure and union specifiers
13 An unnamed member whose type specifier is a structure specifier with no tag is called an anonymous structure; an unnamed member whose type specifier is a union specifier with no tag is called an anonymous union. The members of an anonymous structure or union are considered to be members of the containing structure or union. This applies recursively if the containing structure or union is also anonymous.
The advantage of this feature is that one can access its unnamed union field easier:
type_t x;
To access the field a, you can simply use x.a. Compare with the code without using this feature:
typedef union {
int int32;
int boolean;
time_t date;
char *string;
union u{ //difference in here
struct foo *a;
struct foo *b;
struct foo *c;
};
} type_t;
type_t x;
You need to use x.u.a.
Related: unnamed struct/union in C
I think the intended use-case is more “anonymous union inside a struct”, and the behavior of “anonymous union inside a union” being the same as a “flat” union is just an acceptable compromise for consistency.
Allows the same pointer to be called a, b or c. Maybe there is some legacy code that can't agree on what name to use.
Related
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?
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;
};
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.
I have three structs that share the first type and name of the first field:
struct TYPEA {
char *name;
int x,y; /*or whatever*/
};
struct TYPEB {
char *name;
float a[30]; /*or whatever*/
};
struct TYPEC {
char *name;
void *w,*z; /*or whatever*/
};
If I remember correctly the first field of a struct is required to start at the same address as the struct itself.
This makes me wonder if the same holds for a union:
union data {
struct TYPEA;
struct TYPEB;
struct TYPEC;
};
union data *p = function_returning_a_sane_default_for_union_data();
printf("%s", (char*) p);
I have 2 question regarding this:
are unions required by standard
to always have their content at the same address?
would it work if the structs all had the same
fiels, so differing only in name?
The first element of a struct or union is guaranteed to have the same address-value as the struct´/union itself. Apparently it has not the same type!
For your usage, you do not need the cast and actually should avoid it:
6.5.2.3p6: One special guarantee is made in order to simplify the use of unions: if a union contains several structures that share a common initial sequence (see below), and if the union object currently contains one of these structures, it is permitted to inspect the common initial part of any of them anywhere that a declaration of the completed type of the union is visible. …
So you could (see below) simply
printf("%s", p->name);
(Note: that your usage of unnamed union members is not standard compilant. It is a (very useful) gcc extension (-fms-extensions, at least also supported by MSVC, too).)
But: The code in your question is wrong. You have to name each union member or have the type declarator with each member. With the same first member, It will not weork, though, because the names of the mebers of such unnamed members have to be unique (how else are they supposed to be accesseed individually?). So this will not really work. What you could do is:
union data {
struct TYPEA typea;
struct TYPEB typeb;
struct TYPEC typec;
};
and
printf("%s", p->typea.name);
even if the struct contains a value of TYPEB currently.
An alternative and more clear way, would be to wrap the union into a struct:
struct TypeA {
int x,y;
};
...
struct data {
char *name;
union {
struct TypeA;
struct TypeB;
struct TypeC;
};
};
This also uses the gcc extension at two levels: for the outer struct and the union. As such, it requires unique names for all possible paths. If you want to be 100% compliant, name each member like above and use the full path on access.
Note: I removed the name member from the inner structs in the union and moved it to the outer struct. I also changed names. The only well accepted naming convention in C is to use all-uppercase for macros only.
So you can do this to create c1 and c2 as instances of struct Complex:
struct Complex {
int real;
int imag;
} c1, c2;
And you can do this to typedef the anonymous struct:
typedef struct { ... } Complex;
But is there any way to do both at once?
No, you can't. typedef's syntax is
typedef T type_ident; // T is type specified by the declaration specifiers
This means that anything after typedef T will be a type name, not the instance of that type. So, in
typedef struct { ... } Complex, c1, c2;
Complex, c1 and c2 are all typedef name with the type struct { ... }.
The standard (PDF) says it's impossible, cause typedef is just one of the type specifiers. It's as if you had written char int a;.
Storage-class specifiers (typedef, static, extern etc) always apply to the whole declaration. In the same way that one declaration cannot declare static and non-static variables, a typedef declaration can only define type definitions:
static int foo, bar; // Both foo and bar are static
typedef int c1, c2; // Both c1 and c2 are typedefs
The first form declares a structure tag; the second declares a typedef. The main difference is that the second declaration is of a slightly more abstract type,if users don't necessarily know that it is a structure, and the keyword struct is not used when declaring instances of it...& Structures declared with tags, on the other hand, must be defined..So its not possible create c1 and c2 as instances of struct Complex....
Say I have the following types:
typedef struct TYPEA
{
int type;
char[12] id;
} TYPEA;
typedef struct TYPEB
{
int type;
int value;
} TYPEB;
I want to use create a union of these types and 'int', so that I can access the "type" int without needing to know whether TYPEA or TYPEB is stored in the union (the value of int lets me determine which is actually stored there). I can't get the right syntax though.
My union:
typedef union MEMBER
{
int type;
struct TYPEA a;
struct TYPEB b;
} MEMBER;
The union is accessed via:
typedef struct WRAPPER
{
union MEMBER* member;
struct WRAPPER* next;
} WRAPPER;
Questions:
(With 'w' as a pointer to an allocated WRAPPER struct) Accessing using w->member->a.id gives "request for member 'id' in something not a structure or union.
Can I assign a pointer to an already malloc'd TYPEA/B to w->member directly? Or does a union need to be malloced specially?
Thanks.
Use w->member->type.
You need to allocate the union specifically.
One note that may be a point of misunderstanding is that the union holds EITHER the int, or TYPEA, or TYPEB, so in particular you cannot rely on your int type; in the union to tell you which struct the union holds.
Edit to respond to question in comments:
You probably want something like this:
struct TYPEA {
char data[30]; // or whatever
};
struct TYPEB {
double x, y; // or whatever
};
struct some_info {
int type; // set accordingly
union {
struct TYPEA a;
struct TYPEB b;
} data; // access with some_info_object.data.a or some_info_object.data.b
};
You defined the member field as a pointer, so you should use
w->member->type instead of w->member.type.
You should malloc the union type. When you allocate a union, you'll get a structure that has a sizeof equal to the largest element in the union. If you try to copy structures into union pointers, you'll mess up the alignment.
w->member.type should be w->member->type because w->member is a pointer.
I don't know off the top of my head whether C will let you assign a TYPEA* or TYPEB* to a MEMBER* - somehow I doubt it. You can always (MEMBER*) it, but I would consider recomposing the structs to remove the int tag and instead declare one struct that includes the tag and a union of TYPEA and TYPEB. The structs ideally shouldn't need to be concerned with the fact that they're in a union.
You might want to check out the code in my question:
Union of structs with common first member
Essentially, I do what you want but I'm using an inner struct (contained in the example) that's common to the two types. This struct can then be cast to gain access to the common elements of both types.
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?
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;
};
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.