union inside union is it OK? [duplicate] - c

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.

Related

Accessing first field of struct in a union of structs

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.

Where to place a nested union in a struct in C?

I have an anonymous union nested within a struct, as well as other common fields. Is there any reason to place the union in a specific place within the struct (e.g. first or last)?
For example, is this:
typedef struct _Message
{
MessageType type;
union
{
SystemMessageArgs systemArgs;
OtherMessageArgs usbArgs;
};
} Message;
better than this:
typedef struct _Message
{
union
{
SystemMessageArgs systemArgs;
OtherMessageArgs usbArgs;
};
MessageType type;
} Message;
in any way?
The context is embedded-C, specifically TI's MSP430
There may be a possible difference in padding, you can find that out by using sizeof() on both of them and comparing the results. This may be relevant if you are dealing with heavily constrained memory amounts.
Other than that, they are equivalent.

Union - How do you know which union parameter is in use?

I have the following piece of code:
struct sched_param {
union {
int sched_priority;
struct rcost_sched_param rcost_params;
};
};
I want to know which of the two parameters is "active". Is there a way for me to do that other than adding a int to the struct sched_param?
struct sched_param {
int type;
union {
int sched_priority;
struct rcost_sched_param rcost_params;
};
}
you can add member named type,save the data which parameters is "active"
No, that's the tricky part here: You'll have to store the information which union entry to use (e.g. using a single char member). Also note that both union entries might not necessarily point to the same locations (as you might expect, e.g. due to packing or endianess), so you can't just read one value and determine whether it's containing a valid value or not, since it's up to the compiler how to implement the struct in the union behind the scenes.

Uniform handle parameter for multiple datatypes in C

This is in C. I have a handle which I use throughout many files (let's call it type_handle), which is an enum presently, but currently I would need to extend it to support a typedef-ed struct (called my_type) as well. Since many functions take type_handle as an input parameter, I don't want to change the design majorly so that I need to redo all the files. So my idea is to pass int, float, double and then my_type. I want to have some sort of a union function of all types I want, so that I don't need to modify functions taking type_handle. How should I design this?
typedef enum
{
INT = MPI_INT,
INT8 = MPI_INT8_T,
INT16 = MPI_INT16_T
}
types_t;
typedef union {
my_type dtype;
types_t etype;
} type_handle;
I want to design this in a way such that any_func(type_handle type) could accept any_func(INT) as well as any_func(dtype) where dtype is say a derived datatype of type my_type.
When using a union in C you need some way to know which member to use. C itself cannot tell you which element of your union is the one you assigned. This will be confusing to explain, since you are already dealing with types, but the idiom would be:
struct {
what_is_in_the_union_t what;
union {
type_a a;
type_b b;
...
} u;
};
Where what_is_in_the_union_t is your own enum of { TYPE_A, TYPE_B, ... }. As I said, this will expand in a confusing way in your example because your inner type_a is already a types_t.

Unions within unions

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.

Resources