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.
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.
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.
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.
Inside of this first step towards a bootstrapped scheme interpreter I find the following set of typedef, struct, union, and enum definitions:
typedef enum {FIXNUM} object_type;
typedef struct object {
object_type type;
union {
struct {
long value;
} fixnum;
} data;
} object;
In particular, I'm not sure I understand the point of the struct inside the union (struct { long value; } fixnum;) -- a struct with only one field, to hold a single long? Very strange.
But I'm not really sure I understand the larger point, too. I think what's going on with the enum definition is that he's setting up a number of possible type values for lexical entities, and that object is a way of holding these, but perhaps somebody with more practice in C than I have can offer a more detailed explanation.
Thanks!
You're right, the struct-inside-a-union-inside-a-struct is rather useless in this code, but the author is using it as a stepping stone for the later code. Since he knows what the future code is going to look like, he can prepare the earlier code to make the changes as minimal as possible.
In the second part of the tutorial, the definition expands to this:
typedef enum {BOOLEAN, FIXNUM} object_type;
typedef struct object {
object_type type;
union {
struct {
char value;
} boolean;
struct {
long value;
} fixnum;
} data;
} object;
Now an object can hold two different values (a boolean or an integer), so the union now serves a purpose. The inner structures are still redundant, though. Notice how none of the code dealing with fixnums has to change.
I suspect that the inner structures are there just for parallelism. In v0.6, the author adds the pair type, which consists of a structure of two pointers.
You're correct. This is going to be a single type which can hold a number of different typed values.
This is the first step. The second step will be to add another type to this.
To do that, you'll add an type ID to the enum and add the value itself to the union, something like:
typedef enum {FIXNUM,FLOATNUM} object_type;
typedef struct object {
object_type type;
union {
struct { long value; } fixnum;
struct { float value; } floatnum;
} data;
} object;
As to the reason why you have single-field structures, my guess is that they're allowing for the possibility of multi-field structures later on:
typedef enum {FIXNUM,FLOATNUM,STRING} object_type;
typedef struct object {
object_type type;
union {
struct { long value; } fixnum;
struct { float value; } floatnum;
struct { size_t len; char *data; } string;
} data;
} object;
That's just supposition on my part, it will probably become clear as you advance through the iterations why they chose to do it that way.