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
我正在 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