Search code examples
carraysstructsizeofflexible-array-member

Using the sizeof operator in the initialization of a struct with a flexible array


I want to declare a struct with a flexible array member in it, and then use sizeof() on it. The prototype is:

typedef struct
{
    uint16_t    length;
    uint8_t     array[][2];
} FLEXIBLE_t;

I then declare it:

const FLEXIBLE_t test = {
    .length = sizeof(test),
    .array = {  {   0,  1   },
                {   2,  3   },
                {   4,  5   },
                {   6,  7   },
                {   8,  9   } }
};

Everything compiles okay (GCC) but when I examine test.length it has the value 2, i.e. it is only counting the uint16_t for length itself.

How can I calculate the size of the struct at compile time? It appears that the compiler uses the prototype rather than the specific instance.


Solution

  • GCC allows initializing flexible arrays as an extension: https://gcc.gnu.org/onlinedocs/gcc-4.4.0/gcc/Zero-Length.html

    However, sizeof() follows the C standard and considers flexible arrays in structs to have a size of zero. In any case, when trying to use sizeof() in the initializer of the struct, the struct is incomplete at that stage and the final size not yet known. Only the size of the prototype, with its zero-length flexible array, is known.

    The size is known at compile time however, just not until after the struct has been initialized. GCC's __builtin_object_size() will evaluate to a numeric constant in this instance, but must be called from a function as it is not always constant and as such cannot be used in the initializer.

    So .length must be assigned at run time, but at least the value being assigned compiles down to a constant:

    test.length = __builtin_object_size(test, 0);