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方法,这将导致表中出现空指针,如果这些指针出现问题,则可以很容易地进行调试。如果我忘记用这个方法更新字符串表,我会得到更难调试的segfults。如果我必须记住偏移量的话,它也会破坏符号的意义。
如果声明在一个函数中,我可以实现如下所需的效果:
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中有没有方法声明这样一个字符串表?
(组装没问题。)
最佳答案
#define DEF_FOO_ENUM(E0, S0, E1, S1, E2, S2) \
enum foo { E0, E1, E2 }; \
const char *foo_str = { S0, S1, S2 };
DEF_FOO_ENUM(THING_FOO, "foo",
THING_BAR, "bar",
THING_BAZ, "baz");
符号和字符串是成对的。不使用字符串就不容易添加新符号,反之亦然。若要添加元素,必须为宏添加两个新参数-
E3, S3
-等等。这里没有什么可以保持同步的,只是enum
有所有的E
-s,而数组有所有的S
-s。这几乎不可能搞砸。