There are a number of C idioms that (as a primarily C++ programmer) make my skin crawl when I see them.
Idiom 1
struct A
{
int id;
int bar;
char *quux;
};
struct B
{
int id;
double foo1;
double foo2;
};
struct C
{
int id;
void *something;
};
union X
{
int id;
struct A a;
struct B b;
struct C c;
};
union X x;
I see this done in, for example, GTK+, which handles events this way. There are a group of structs each containing information about a specific type of event, each starting with an int id
that lines up with X.id
such that it can be used to determine what sort of structure within the union is actually initialized.
Idiom 2
struct A
{
int count;
};
struct B
{
struct A a;
void *foo;
float bar;
};
struct X
{
struct B b;
int wibble;
int wobble;
int wubble;
int flob;
};
struct X *x = make_X(); // malloc me an X and initialize it
I see this idiom used for active reference counting of C objects. The specific part of the idiom that scares me is the part where, in order to get at the reference count data, our struct X*
is cast directly to a struct A*
which relies on the structs being created with no padding, and with their elements in the order specified in the definition.
Question
Are those idioms well defined in C? Sometimes, always, never? Empirical evidence suggests that they will work under some circumstances, but I don't know if they're working because they're defined to work, or if they're relying on some sort of undefined behavior. The fact that GTK relies on one of them doesn't really make me any more willing to believe that it's well defined, it wouldn't be the first time that the linux guys relied on platform specific behavior. I'd really appreciate some links to relevant parts of the standard, but I'm not really sure where to start looking.