确保数组在编译时填充大小

时间:2016-01-08 03:46:25

标签: c arrays

如何在编译时确保COLOR_NAMES填充到正确的大小?如果添加了一种新颜色,比如COLOR_4(因此N_COLORS自动递增),编译器会告诉我COLOR_NAMES没有填充大小。

我在网上找到的大多数答案都是针对运行时而非编译时间。

这是用于C风格的表示法(没有STL和其他库使用)。

enum Colors
{
   COLOR_1,
   COLOR_2,
   COLOR_3,
   N_COLORS;
};

const char* COLOR_NAMES[N_COLORS] =
{
   /* COLOR_1 */ "Color1",
   /* COLOR_2 */ "Color2",
   /* COLOR_3 */ "Color3"
};

const char* Blah()
{
   Colors color;
   ...
   printf("%s blah blah\n", COLOR_NAMES(color));
}

3 个答案:

答案 0 :(得分:1)

理想的是能够使用预处理器中的sizeof。但我们不能,因为sizeof是由编译器评估的。

有很多方法可以绕过这个,但这里有一个非常简单和便携的方法:

const char* COLOR_NAMES[] = {
   /* COLOR_1 */ "Color1",
   /* COLOR_2 */ "Color2",
   /* COLOR_3 */ "Color3"
};

typedef char CHECK_COLOR_NAMES[sizeof(COLOR_NAMES) / sizeof(COLOR_NAMES[0]) == N_COLORS ? 1 : -1];

如果测试失败,您将尝试定义大小为-1的数组,这将导致编译错误。

编辑:然后我们使用typedef来避免实际创建一个我们不会使用的变量(Lundin的评论)

答案 1 :(得分:1)

对于此类数组和相应枚举的情况,标准做法是将您的案例中的"枚举大小成员",N_COLORS与数组中的项目数进行比较。

要获取数组中的项数,只需将数组大小除以一个数组成员的大小。

因此:

_Static_assert(sizeof(COLOR_NAMES)/sizeof(*COLOR_NAMES) == N_COLORS, 
               "Array item missing!");

修改

哦,顺便说一下,这个数组声明必须是const char* COLOR_NAMES[] =才有意义,否则你就无法判断数组初始化列表中是否缺少初始值设定项。

答案 2 :(得分:0)

使用constepxr,您可以使用:

constexpr static const char* COLOR_NAMES[N_COLORS] =
{
   /* COLOR_1 */ "Color1",
   /* COLOR_2 */ "Color2",
   /* COLOR_3 */ "Color3"
};

static_assert(COLOR_NAMES[N_COLORS-1] !=0);

如果要使用局部变量,可以使用变量

constexpr variant<const char*> COLOR_NAMES[N_COLORS] =
{
   /* COLOR_1 */ "Color1",
   /* COLOR_2 */ "Color2",
   /* COLOR_3 */ "Color3"
};

static_assert(get<0>(COLOR_NAMES[N_COLORS-1]) !=nullptr);