C99 允许数组初始值设定项(以及其他)指定要使用正整数指示符设置数组的哪个元素($6.7.8.6、$6.7.8.17),例如:
const char *foo[] = {[2] = "foo", [1] = "bar", [0] = "baz"};
我以前用它来制作一个枚举到字符串的表,如下所示:
enum {THING_FOO = 0, THING_BAR, THING_BAZ};
const char *table[] = {
[THING_FOO] = "foo",
[THING_BAR] = "bar",
[THING_BAZ] = "baz"
}
但是,我现在的工作要求我的代码符合 c89。
我研究了预处理器魔法(例如 here),但我需要字符串是任意的,而不是枚举符号的副本。
光做是不够的
enum {THING_FOO = 0, THING_BAR, THING_BAZ};
const char *table[] = {"foo", "bar", "baz"};
因为我以后需要添加枚举元素。使用 c99 方法,这将导致表中出现 NULL 指针,如果它们成为问题,则很容易调试。如果我忘记使用这种方法更新字符串表,我会得到更难调试的段错误。如果无论如何我都必须记住偏移量,它也会破坏使用符号的意义。
如果声明在一个函数中,我可以像这样达到预期的效果:
enum {THING_FOO = 0, THING_BAR, THING_BAZ, NUM_THINGS};
void foo(void)
{
static const char *table[NUM_THINGS];
table[THING_FOO] = "foo";
table[THING_BAR] = "bar";
table[THING_BAZ] = "baz";
/* ... */
}
但是,至少对于 gcc
,这没有得到优化。
有没有办法在c89中声明这样一个字符串表?(组装没问题。)
简单的,老式的
const char* table[] = { "foo", "bar", "baz" };
换句话说,只要按正确的顺序排列即可。
char *foo_string = table[FOO];
当然,这只适用于像上面这样的简单枚举,不适用于样式中的枚举
enum { FOO = 13; BAR = 15, BAZ = 312 };
但为此,您必须创建一个至少包含 313 个元素的数组,其中大部分元素无论如何都是 NULL,这将是一个非常浪费的结构。在这种情况下,当您使用 switch
结构时,编译器可以为您优化。
另请参阅 S.O. @Leandros 指出的问题:How to convert enum names to string in c .那里的答案使用宏来生成数组,以确保条目的顺序正确。
或者,正如那个答案所说:
#define enum_str(s) #s
这完全摆脱了数组。
我是一名优秀的程序员,十分优秀!