我目前正在尝试对结构数组执行编译时检查,以确保如果有人在将来更改它,则会定义数组的每个元素。我想避免有人向struct-of-struct添加太多元素的情况,如果我明确设置数组大小,这是可能的。这不包括有人为数组定义的元素太少而其余元素只是零初始化的情况。
#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;
}
这似乎是一个声音检查,因为在编译时评估sizeof()
。但是编译器报告:
test.c:15:12: error: missing binary operator before token "("
test.c:19: error: expected ',' or ';' before 'int'
如果可能的话,我可以如何实施这样的检查?
谢谢。
答案 0 :(得分:2)
您必须使用预处理阶段之后编译器的功能。
C11有_Static_assert
:
_Static_assert(ARRAY_SIZE == RATIO);
那将是最干净的解决方案。如果你没有,你可以使用
这样的技巧typedef char something_useless[ARRAY_SIZE == RATIO];
如果比较评估为1
,则这是一个无效的typedef
。如果是0
并且将发生错误(约束违规)。
答案 1 :(得分:1)
预处理器不评估sizeof()。这是编译器完成的事情。
编译C程序有两个主要阶段,预处理器阶段只进行文本转换,第二个主要状态是编译预处理器的输出。
这意味着预处理器不会对C变量和结构进行评估,因此您的决定无效。
您可以考虑使用ASSERT()宏来断言特定条件。如果启用ASSERT()以展开ASSERT()宏,则在运行时评估它们。
我实际上编写了自己的版本,将特定的断言放入某些函数中,对结构的大小进行运行时检查。使用我自己的断言宏,我可以有选择地打开和关闭它们。
使用我自己的断言宏,我有一个函数可以创建断言的日志,如果构建是一个调试版本,例如用于设计器测试,函数将执行一个中断,以便设计人员看到断言立即失败并能够进行堆栈跟踪并采取其他步骤来确定断言发生的原因。
我使用的基本卷你自己的断言宏是:
#define NHPOS_ASSERT(x) if (!(x)) { PifLogAbort( (UCHAR *) #x , (UCHAR *) __FILE__ , (UCHAR *) "function" , __LINE__ );}
其中PifLogAbort()
是生成日志文件的函数。使用这个我可以看到断言的条件以及文件名和行号。