如何在不分配全局变量的情况下获取宏中的元素数量
Absolutely! You don’t need to waste memory on an unused sub_array just to get the length of your SUB_LIST macro. There are a couple of clean, compile-time solutions that avoid any runtime memory overhead.
Method 1: Use a Compound Literal Inside sizeof (C99+)
This is the most flexible approach and works with almost all modern compilers (since C99 is widely supported today). The key insight here is that sizeof calculates the size of a type at compile time—it does not allocate actual memory for the temporary array we create:
#define SUB_LIST 1, 2, 3 // Macro to count elements in a variadic list #define COUNT_LIST_ELEMENTS(...) \ (sizeof((uint8_t[]){__VA_ARGS__}) / sizeof(uint8_t)) // Calculate the list size at compile time #define SUB_LIST_SIZE COUNT_LIST_ELEMENTS(SUB_LIST) // Use the size directly—no extra array needed! uint8_t array[SUB_LIST_SIZE + X] = {0};
How this works:
(uint8_t[]){__VA_ARGS__}creates a temporary compound literal array holding yourSUB_LISTelements.sizeofcomputes the total byte size of this array during compilation. Dividing bysizeof(uint8_t)gives you the exact number of elements.- Since all calculations happen at compile time, no runtime array is allocated—completely eliminating the memory waste from your original approach.
Method 2: Preprocessor Argument Counting (C89 Compatible)
If you need to support older C standards (C89), you can use a preprocessor trick that counts arguments by matching them to a predefined list of numbers. This requires setting a maximum expected number of elements, but it works without C99 features:
#define SUB_LIST 1, 2, 3 // Helper macro to pick the count from the argument list #define _COUNT_ARGS(_1, _2, _3, _4, _5, COUNT, ...) COUNT // Count up to 5 elements—extend the number list if you need more #define COUNT_LIST_ELEMENTS(...) \ _COUNT_ARGS(__VA_ARGS__, 5, 4, 3, 2, 1, 0) #define SUB_LIST_SIZE COUNT_LIST_ELEMENTS(SUB_LIST) uint8_t array[SUB_LIST_SIZE + X] = {0};
How this works:
- When you pass
SUB_LIST(1, 2, 3) toCOUNT_LIST_ELEMENTS, it expands to_COUNT_ARGS(1, 2, 3, 5, 4, 3, 2, 1, 0). - The
_COUNT_ARGSmacro selects the 6th argument (labeledCOUNT), which in this case is3—the exact number of elements in your list. - If you need to support more than 5 elements, just add larger numbers to the end of the
_COUNT_ARGScall (e.g.,6, 5, 4, ...).
Why Your Original Approach Wastes Memory
In your original code, sub_array is a fully allocated array (stored in your program’s data or BSS segment) even though you never use it. The compile-time methods above avoid this entirely—all counting happens before your program runs, with zero runtime memory cost.
内容的提问来源于stack exchange,提问作者The_Average_Engineer

