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中声明这样的字符串表? (这在组装中没有问题。)
答案 0 :(得分:2)
#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。这几乎是不可能搞砸的。
答案 1 :(得分:1)
简单,老式的
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
完全摆脱阵列。
答案 2 :(得分:1)
您可以使用X-Macros将它们保持在一起:
actionProgram()
现在您的新数据可以添加为一组枚举和字符串。如果您以后决定根据枚举添加其他内容,则可以使用' z' OP()或甚至#define MYXMACRO(OP) \
OP(ENUM_FOO, "foo") \
OP(ENUM_BAR, " bar") \
OP(ENUM_BAZ, "baz")
/* use the first parameter to set up your enums*/
enum {
#define AS_ENUMS(x,y) x,
MYXMACRO(AS_ENUMS)
#undef AS_ENUMS /*not required, just playing nice*/
NUMTHINGS
};
/* use the 2nd parameter to set up your strings*/
const char *strings[] = {
#define AS_STRINGS(x,y) y,
MYXMACRO(AS_STRINGS)
#undef AS_STRINGS
};
#undef MYXMACRO
和...
的参数,用于多个但数量不同的参数。
答案 3 :(得分:0)
在尝试了几种不同的技术之后,这个技术最容易维护:
const char *table[] = {
#define FOO 0
"foo",
#define BAR (FOO + 1)
"bar",
#define BAZ (BAR + 1)
"baz"
}
此处有关条目的所有信息都是群集的。要插入元素,您只需要修改它周围的东西。例如,插入qux
:
const char *table[] = {
#define FOO 0
"foo",
#define QUX (FOO + 1) /* new */
"qux", /* new */
#define BAR (QUX + 1) /* modified */
"bar",
#define BAZ (BAR + 1)
"baz"
}
它有点难看(有点可爱,你知道吗?)但是效果很好。