c 中的常量数组 - 检查是否所有元素都在编译时定义

constant array in c - check if all elements are defined during compile time

我正在 C 中寻找一种方法,以在编译时检查是否设置了常量数组的所有元素。背景是,我想要一个带有命名行的查找-table,它必须是完整的。

示例:

typedef enum [foo, bar, bla, max_value} rowNames;

static const uint32 LookupTable[max_value] =
{
    [foo] = 123,
    [bla] = 456, // oops, someone forgot to define the value for [bar]
}

retval = LookupTable[bar]; //this is to read out the value of the lookup table at a certain position

在此示例中,有人忘记为数组元素 #1 [bar] 定义值。我想确保在编译期间,所有值都已定义,错误会破坏构建。

当然在现实中 table 会更大更复杂,但我认为这已经足够了。特别是如果稍后编辑枚举,很可能枚举和 table 定义不一致。

此致, 阿恩斯基

由于您希望它在编译时发生,我认为您唯一的选择是创建一个静态代码分析器来执行此检查,并将其添加到您的工具链中,以便在每次构建时进行验证。

在 运行 时,您可以在枚举末尾使用该条目 ('max_value'),并将其与查找的大小 table 进行比较,只要您将 table 定义更改为

static const uint32 LookupTable[] =
{
    /*[foo] = */123,
    /*[bla] = */456
}

这样,数组是自动调整大小的,sizeof 可以用来查看其中有多少条目,所以一旦有人更改枚举,他们至少会得到一个 运行时间下次他们 运行

时出错

这可以很容易地完成,只需对您的代码进行一些修改。

将数组更改为static const uint32 LookupTable[],使其大小取决于初始化的项目数。然后在没有指定初始化器的情况下初始化数组,只是:

static const uint32 LookupTable[] =
{
  123, // foo
  456, // bla
  ...
};

现在您的标准 C 编译器可以使用编译时断言检查数组的完整性:

_Static_assert(sizeof LookupTable / sizeof *LookupTable == max_value, 
               "LookupTable wrong number of items");

编辑:

为了严格控制数据,可以使用“X 宏”技巧,它会创建非常丑陋的代码,但会将所有数据集中到源中的一个位置。在我下面的示例中,所有数据信息都存储在宏 ARRAY_LIST:

#include <stdio.h>

#define ARRAY_LIST(X) \
  X(foo, 1)           \
  X(bar, 2)           \
  X(bla, 3)           \

typedef enum
{
  #define FOO_ENUM(name,val) name,
  ARRAY_LIST(FOO_ENUM)
  foo_n
} foo_t;

const int array[] =
{
  #define ARRAY_INIT(name,val) [name] = val,
  ARRAY_LIST(ARRAY_INIT)
};

_Static_assert(sizeof array / sizeof *array == foo_n, 
               "LookupTable wrong number of items");

int main (void)
{
  #define PRINT_ITEM(name,val) printf("%s: %d\n",#name, array[name]);
  ARRAY_LIST(PRINT_ITEM)
}

预处理器输出然后给出:

typedef enum
{
  foo, bar, bla,
  foo_n
} foo_t;

const int array[] =
{
  [foo] = 1, [bar] = 2, [bla] = 3,
};

_Static_assert(sizeof array / sizeof *array == foo_n,
               "LookupTable wrong number of items");

int main (void)
{
  printf("%s: %d\n","foo", array[foo]); 
  printf("%s: %d\n","bar", array[bar]); 
  printf("%s: %d\n","bla", array[bla]);
}

程序输出:

foo: 1
bar: 2
bla: 3