问题
I want to use the C preprocessor to count the amount of lines between two code locations. The basic idea is something like this:
#define START __LINE__
static char* string_list[] = {
"some string",
"another string",
...
"last string"
};
#define END __LINE__
#if END - START > 42
#error Too many entries
#endif
Of course this doesn't work because in this case START
and END
are merely redefinitions of the __LINE__
macro.
I was playing around a bit with the #
and ##
operators, but I could not get the preprocessor to evaluate START
and END
while the preprocessor is running.
My question is: is this possible at all?
Checking the size of the array during runtime is not an option.
Thanks for any hints or ideas in advance!
回答1:
You shouldn't use those macros for that purpose: the code will become completely unmaintainable if you introduce an extra line somewhere. And what if there are too few lines?
Instead of macros, use a static assert:
static_assert(sizeof(string_list) / sizeof(*string_list) == SOME_CONSTANT,
"Wrong number of entries in string list.");
If you aren't using C11 which has support for static_assert, you can write such an assert yourself, for example like this:
#define COMPILE_TIME_ASSERT(expr) {typedef uint8_t COMP_TIME_ASSERT[(expr) ? 1 : 0];}
回答2:
[Acknowledge @Lundin who points out that you can use a typedef
]
This is one way
typedef uint8_t START[__LINE__]; /*put this on one line*/
typedef uint8_t END[__LINE__]; /*put this on another line*/
sizeof(END) - sizeof(START)
is a compile-time expression giving the line offset.
Put in macros and rename START
and END
to taste.
回答3:
If you declare the array thus:
static const char* string_list[42] = {...
The compiler will tell you if you provide too many initialisers. You can provide a sentinel entry to mark the end if necessary:
static char* string_list[43] = { ..., NULL } ;
And perhaps write a function to determine the length at runtime if you need to know that.
来源:https://stackoverflow.com/questions/24551721/count-lines-between-two-code-locations-in-c-preprocessor