Search code examples
cmemoryembedded

C: Initialize custom array size in struct at compile time


Consider the following code:

typedef struct Object
{
  uint8_t size;
  uint8_t array[];
}Object;

How would I make the Object with a compile time but user defined size array?

After reading some stackoverflow posts and trying the code myself I now know that as long as I use at least the compiler standard C99 I can declare the Object with a custom size like this:

Object o = {.size = 2, .array = {1, 2}};

But what I want is just an empty array with a custom size so instead of typing

Object o = {.size = 5, .array = {1, 2, 3, 4, 5}};

i want to type something like

Object o = {.size = 5, .array = uint8_t[5]};

What is also important is, that I need to know the array size at compile time and can't use dynamic memory like malloc so the typical solution of a flexible array member which is just allocated with the use of malloc wouldn't work for me.

Does a solution like this exist?

If it does not exist: Why would the first example work (for some compilers) but just telling the compiler I need a size 10 array in the struct at compile time without initializing the values in it would not?

Edit: I guess I should have made clear that my goal was to create something similar to the C++ std::array since with that datatype the user can just choose the size of the array without having to know the inner workings and rewriting the struct for every new size.


Solution

  • You can use a union defined within a compound literal:

    Object *o = &(union { Object o;
                          // anonymous struct
                          struct { uint8_t size; uint8_t array[N]; };
                        } ) { .size = N }.o;
    

    It can be quite well packed into a macro.

    It compiles without a warning in pedantic mode producing the expected results for both global and stack-allocated object. See https://godbolt.org/z/jhsbMseY8

    This solution is guaranteed to work because in C the two struct members of the union can alias as long as they share common initial subsequence.