C在编译时检查数组内容

C在编译时检查数组内容,c,arrays,compile-time,C,Arrays,Compile Time,我有一个枚举和一个结构数组。结构中的第一个字段是枚举类型。现在我想在编译时检查第一个数组元素的第一个字段中的值是否与枚举类型的第一个值相同。与第二个元素相同,依此类推 基本上是这样的: typedef enum { A = 0, B, C } enumerator1; typedef struct { enumerator1 a; unsigned char foo; unsigned char bar; } structure1; const str

我有一个枚举和一个结构数组。结构中的第一个字段是枚举类型。现在我想在编译时检查第一个数组元素的第一个字段中的值是否与枚举类型的第一个值相同。与第二个元素相同,依此类推

基本上是这样的:

typedef enum {
   A = 0,
   B,
   C
} enumerator1;

typedef struct {
   enumerator1   a;
   unsigned char foo;
   unsigned char bar;
} structure1;

const structure1 array1[3] =
{
   {A, 1, 1},   //This element should contain A
   {C, 1, 1},   //This element should contain B
   {B, 1, 1}    //This element should contain C
};
#if array1[0].a != A
#error
#endif
typedef unsigned char Check[(array1[0].a != A) ? 1 : -1];
在上面的示例中,B和C是交换的,我希望在编译时捕捉到这一点。 我要找的是这样的东西:

typedef enum {
   A = 0,
   B,
   C
} enumerator1;

typedef struct {
   enumerator1   a;
   unsigned char foo;
   unsigned char bar;
} structure1;

const structure1 array1[3] =
{
   {A, 1, 1},   //This element should contain A
   {C, 1, 1},   //This element should contain B
   {B, 1, 1}    //This element should contain C
};
#if array1[0].a != A
#error
#endif
typedef unsigned char Check[(array1[0].a != A) ? 1 : -1];
但这不起作用,编译器说“令牌”[“在预处理器表达式中无效”。 我也试过这样的方法:

typedef enum {
   A = 0,
   B,
   C
} enumerator1;

typedef struct {
   enumerator1   a;
   unsigned char foo;
   unsigned char bar;
} structure1;

const structure1 array1[3] =
{
   {A, 1, 1},   //This element should contain A
   {C, 1, 1},   //This element should contain B
   {B, 1, 1}    //This element should contain C
};
#if array1[0].a != A
#error
#endif
typedef unsigned char Check[(array1[0].a != A) ? 1 : -1];
但结果是一样的。 如果可能,我如何实施这样的检查


谢谢。

不行。C中的数组在概念上是一种运行时的东西。没有可移植的方法来强制对其进行comptime断言

这并不意味着优化编译器不会看到它

如果我执行
If(!(array1[0].a==a))abort();
并查看反汇编,我可以看到,当我使用优化进行编译时,gcc和clang都完全忽略了这段代码

有一个GCC技巧,允许您将此优化器知识转换为comptime断言(或ASAP断言) 正如我所说)

#如果(如果)GNUC(如果)&&&!(如果)__
#pragma GCC诊断错误“-瓦洛克大小大于=9999999L”
#恩迪夫
#如果是NDEBUG
枚举{ndebug=1};
#否则
枚举{ndebug=0};
#恩迪夫
#包括
#定义ASAP_断言(X)\
做{\
/*如果可能,即使没有优化器,也可以静态断言它*/\
(void)(内置常数p(X)sizeof(int[(X)1:-1]):0)\
_Bool ASAP_ASSERT=(X);/*防止双重计算*/\
如果(!ndebug){\
/*尝试使优化器将-Walloc大小提高到大于=*/\
_Bool volatile ASAP_ASSERT_uu[(ASAP_ASSERT)?1:-1]\
ASAP_ASSERT__[0]=0\
(无效)尽快断言\
} \
assert(ASAP_assert);/*如果所有静态断言尝试都失败,则动态执行*/\
}而(0)
类型定义枚举{
A=0,
B
C
}统计员1;
类型定义结构{
统计员1A;
未签名的char-foo;
无符号字符条;
}结构1;
常量结构1数组1[3]=
{
{A,1,1},//此元素应包含
{C,1,1},//此元素应包含B
{B,1,1}//此元素应包含C
};
#包括
int main()
{
ASAP_ASSERT(array1[0].a!=a);//在至少使用-O1编译时,将导致gcc上的comptime失败
}

缺点是它是特定于GCC的,运行时开销很小(易失性写入,可以通过将ndebug设置为1来关闭,但这样就不会出现编译时故障)这是一个非常典型的例子:你向我们展示了一个你有问题的解决方案,但你没有告诉我们你试图解决的实际问题。为什么你需要在编译时检查数组的内容?你的用例是什么?枚举是在一个全局头中定义的,并且非常大事实上。数组是在另一个模块中定义的。许多开发人员在这个项目中工作,有时有人(例如)更改枚举、添加一个对象或更改元素顺序,而没有告诉模块的开发人员数组的定义位置,因此这可能会导致错误,但在最坏的情况下,您将看不到错误立即消失,因此我想添加此编译时检查。我知道这是一个应该在项目/配置管理级别上更好地解决的问题。。。