如何在编译时确保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));
}
答案 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);