C 在编译时检查数组内容

标签 c arrays compile-time

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

基本上是这样的:

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
};

在上面的示例中,B 和 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 断言) 正如我所说)。

#if __GNUC__ && !__clang__
#pragma GCC diagnostic error "-Walloc-size-larger-than=999999999L"
#endif

#if NDEBUG
enum { ndebug=1};
#else
enum { ndebug=0};
#endif

#include <assert.h>
#define ASAP_ASSERT(X)  \
        do{  \
            /*if possible, statically assert it even without the optimizer*/ \
            (void)(__builtin_constant_p(X) ? sizeof(int[(X)?1:-1]) : 0); \
            _Bool ASAP_ASSERT=(X); /*prevent double evaluation*/ \
            if(!ndebug){ \
                /*try to make the optimizer raise a -Walloc-size-larger-than=*/ \
                _Bool volatile ASAP_ASSERT__[(ASAP_ASSERT)?1:-1]; \
                ASAP_ASSERT__[0]=0; \
                (void)ASAP_ASSERT__; \
            } \
            assert(ASAP_ASSERT); /*if all static assert attempts fail, do it dynamically*/ \
        }while(0)

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
};
#include <stdlib.h>
int main()
{

    ASAP_ASSERT(array1[0].a!=A); //will cause a comptime failure on gcc when compiled with at least -O1
}

缺点是它是 GCC 特定的,运行时成本很小( volatile 写入,您可以通过将 ndebug 设置为 1 来关闭它,但这样您就不会遇到编译时失败),并且我遇到了一些问题误报。

关于C 在编译时检查数组内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54626827/

相关文章:

c - C使用构造函数创建结构数组

c - 用 C 语言填满磁盘可用空间的最快方法是什么?

android - Android Studio和gradle的构建速度很慢,与此同时该怎么办?

c++ - 就 size_t 而言, "size of the largest possible object on the target platform"是什么

c - 从子进程运行命令

javascript - React JS : Filtering an array of objects by another array of objects. 如何顺序执行四个函数,包括。多次 API 调用

ios - UITableView 中的 NSUserDefaults 和持久性

javascript - 获取javascript数组中每个键的最大值

Java编译时错误和异常处理中的多个catch block

c++ - 如何实现decltype功能-C++ 11之前的编译时间