Search code examples
arrayscmacrospreprocessor

Get number of element in macro without allocating global variable


I have the following code:

#define SUB_LIST 1, 2, 3

uint8_t sub_array[] = {SUB_LIST};

#define SUB_LIST_SIZE (sizeof(sub_array) / sizeof(sub_array[0]))

uint8_t array[SUB_LIST_SIZE + X] = {0};

Here, sub_array[] exists only because I need it to get the number of elements in SUB_LIST. It is not used anywhere else, and thus it is quite a waste of memory.

It is possible to get the number of element in SUB_LIST without having to permanently allocate memory for sub_array[]?


Solution

  • You can use a compound literal but it gets a bit messy if you want to avoid specifying the element type (here uint8_t) twice:

    #define SUB_LIST_SIZE ( sizeof( (uint8_t[]){SUB_LIST} ) / sizeof(uint8_t) )
    

    With this, a local, unnamed array will be created wherever the SUB_LIST_SIZE macro's code is encountered. That will be created with automatic storage duration (typically, on the stack), or may even optimized out by the compiler. 1

    A short demo:

    #include <stdio.h>
    #include <stdint.h>
    
    #define SUB_LIST 1, 2, 3
    #define SUB_LIST_SIZE ( sizeof( (uint8_t[]){SUB_LIST} ) / sizeof(uint8_t) )
    
    int main()
    {
        #define X 42 // For example
        uint8_t array[SUB_LIST_SIZE + X] = { 0 };
        size_t arr_length = sizeof(array) / sizeof(array[0]);
        printf("Array length = %zu\n", arr_length);
        return 0;
    }
    

    1 This assumes that the macro is used at block scope, as it is in your declaration of array in main; if it is used at file scope, then a static (permanent) unnamed array will be created.