1

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.

Community
  • 1
  • 1
Wug
  • 12,956
  • 4
  • 34
  • 54
  • Amazing how those "Linux guys" manage to [support Windows and Mac OS X](http://www.gtk.org/features.php) with their scary code then, isn't it? :) – unwind Jun 11 '14 at 06:59
  • If I had a nickel for every time I'd seen an application that worked on linux break on some other platform out of the box, I wouldn't have bothered going to college, I'd just have bought a beach in Maui and retired on it. – Wug Jun 11 '14 at 07:47

2 Answers2

3

C11 6.7.2.1 Structure and union specifiers p15 says

Within a structure object, the non-bit-field members and the units in which bit-fields reside have addresses that increase in the order in which they are declared. A pointer to a structure object, suitably converted, points to its initial member (or if that member is a bit-field, then to the unit in which it resides), and vice versa. There may be unnamed padding within a structure object, but not at its beginning.

so it is safe to assume that x points to x->b.a.count in your example.

simonc
  • 41,632
  • 12
  • 85
  • 103
2

The C standard specifies that there may be no padding before a structure's first member.

alk
  • 69,737
  • 10
  • 105
  • 255
  • You were 4 minutes earlier than the other guy, so here's an honorable mention. I'd have accepted your answer if you'd cited the section in the standard that says this. – Wug Jun 11 '14 at 07:49
  • 1
    It's perfectly alright this way. As *simonc* took the effort to look up the standard document, he earns the reputation ... 1+ from my side for this - my bad I didn't had the document by hand. @Wug – alk Jun 11 '14 at 08:15