Search code examples
carraysunions

Fill union with a char array member


I have a C union with numerous fields which will very likely have different sizes across different platforms:

union foo {
    int a;
    wchar_t b;
    bar *c;
    baz d;
}

Now I want to add a char array to this union that's exactly as big as I can make it without it causing the entire union to be larger. Something alone the lines of

union foo {
    ...
    char z[sizeof(union foo)];
}

except that won't compile, of course, since union foo's size isn't yet known at that point.

Is there a trick that'll let me "fill" the union with a char array?


Solution

  • First, declare a union with everything but the array,

    union foo_almost {
        int a;
        wchar_t b;
        bar *c;
        baz d;
    };
    

    Then declare the union with everything,

    union foo {
        int a;
        wchar_t b;
        bar *c;
        baz d;
        char z[sizeof(union foo_almost)];
    };
    

    Some folks use macros to do this - declaring the first part as FOO_ALMOST, but all they really save is typing,

    #def FOO_ALMOST \
        int a; \
        wchar_t b; \
        bar *c; \
        baz d;
    union foo_almost {
        FOO_ALMOST
    };
    

    then,

    union foo {
        FOO_ALMOST
        char z[sizeof(union foo_almost)];
    };
    

    Now, sizeof(union foo_almost) and sizeof(union foo) should be the same. However, your compiler may still allocate more memory than taken by an object of type union foo.

    No ugly hacks needed, unless you consider the additional type union foo_almost to be ugly.

    Notice,

    union foo_almost fa;
    union foo f;
    printf("%zu\n", sizeof(fa));
    printf("%zu\n", sizeof(f));