1

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[]?

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
  • Is there a reasonably small maximum number of arguments? Maybe you could use [this answer](https://stackoverflow.com/a/2124385/5264491). – Ian Abbott Aug 19 '22 at 14:20

2 Answers2

1

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.

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
  • In my code, sub_array[] and array[] are global variables. If we take that into account, will the compound literal still be optimized out by the compiler ? (I am using gcc by the way) – The_Average_Engineer Aug 19 '22 at 14:03
  • @The_Average_Engineer That could be a language-lawyer type issue. The cppreference page I linked states that a globally-declared compound literal has static storage duration but, as it can't be used again in your use case, I can't see why a compiler can't optimize it out, if it can evaluate the expression as a compile-time constant. – Adrian Mole Aug 19 '22 at 14:05
  • Ok it is noted. Thank you for your answer. It was very helpful – The_Average_Engineer Aug 19 '22 at 14:15
  • 1
    @The_Average_Engineer Can't you declare your unused `sub_array[]` `static` to improve the chance of it being optimized out? Otherwise you would need link-time optimizations to stand any chance of optimizing out a variable with external linkage. – Ian Abbott Aug 19 '22 at 14:29
  • 1
    https://godbolt.org/z/jYKzcaG5q it will be optimized by gcc even if optimizations are disabled – 0___________ Aug 19 '22 at 14:29
1

Consider a macro such as this:

#define GET_SIZE(...) ( sizeof (uint8_t[]){ __VA_ARGS__} )

Usage:

GET_SIZE(SUB_LIST)

This creates a temporary compound literal array and places your list of item as initializer list to that array. The compound literal will almost certainly get optimized away in any scenario - in your case it will get replaced by the number 3 in the machine code.

Lundin
  • 195,001
  • 40
  • 254
  • 396