Reputation: 19331
I am currently trying to implement a compile-time check on an array-of-structs to make sure that if someone changes it in the future, every element of the array is defined. I want to avoid a case where someone adds too many elements to the array-of-struct, which is possible if I explicitly set the array size. This does not cover the case where someone defines too few elements to the array, and the remaining elements are just zero-initialized.
#include <stdio.h>
typedef struct myStruct {
int a;
int b;
} myStruct_t;
#define ARRAY_SIZE (3)
myStruct_t sArr[] = {
{0, 0},
{1, 1},
{2, 2}
}
#define RATIO (sizeof(sArr) / sizeof(myStruct_t))
#if ARRAY_SIZE != RATIO
#error API issue
#endif
int main(void) {
printf("Testing\n");
return 0;
}
This seemed like a sound check, since sizeof()
is evaluated at compile time. But the compiler reports:
test.c:15:12: error: missing binary operator before token "("
test.c:19: error: expected ',' or ';' before 'int'
How, if possible, can I implement such a check?
Thank you.
Upvotes: 0
Views: 755
Reputation: 79003
You must use features of the compiler that come after the preprocessiong phase.
C11 has _Static_assert
:
_Static_assert(ARRAY_SIZE == RATIO);
That would be the cleanest solution. If you don't have that you can use tricks like
typedef char something_useless[ARRAY_SIZE == RATIO];
If the comparison evaluates to 1
this is a valid typedef
that will just do nothing. If it is 0
and error (constraint violation) will occur.
Upvotes: 2
Reputation: 17713
The preprocessor does not evaluate sizeof(). That is something done by the compiler.
There are two major stages to compiling a C program, preprocessor stage which does text transformations only and the second major state of compiling the output of the preprocessor.
This means that C variables and structs are not evaluated by the preprocessor so your decision is not going to work.
You may consider using the ASSERT() macro to assert specific conditions. These are evaluated at run time if the ASSERT() is enabled to expand the ASSERT() macro.
I have actually written my own version to put specific asserts into some functions to do run time checks on sizes of structs. With my own assert macros I can selectively turn them on and off.
With my own assert macros I have a function that will create a log of the asserts and if the build is a debug build such as is being used for designer testing the function will perform a break so that the designer will see the assert failure immediately and be able to do stack trace and take other steps to determine why the assert happened.
The basic roll your own assert macro I use is:
#define NHPOS_ASSERT(x) if (!(x)) { PifLogAbort( (UCHAR *) #x , (UCHAR *) __FILE__ , (UCHAR *) "function" , __LINE__ );}
where PifLogAbort()
is a function that generated the log file. Using this I can see the condition that asserted along with the file name and the line number.
Upvotes: 1