c - c89 中的指示符

标签 c enums c89 string-table

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

这完全摆脱了数组。

关于c - c89 中的指示符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38546516/

相关文章:

c - 我如何在没有 dirent.h 的情况下访问 C90 中的目录?

c - 如何在 C 中(在 Visual Studio 中)在全局固定大小数组中设置值?

c - C是否需要堆栈和堆才能运行?

c# - 枚举和常量。什么时候使用哪个?

c - 如何比较枚举值

c++ - 为什么作用域枚举允许使用 |使用先前分配的值进行初始化时的运算符?

c - `clang -ansi` 扩展名

C 中数组大小的混淆

c - 二结构一功能

c - "int *nums = {5, 2, 1, 4}"导致段错误