在C中打印枚举映射

在C中打印枚举映射,c,gcc,macros,C,Gcc,Macros,我经常在C中使用enum来访问带有数字数据的数组元素,例如 #define KEYS_MAX 1 #define FIELD_MAX 2 enum {FIELD1=0, FIELD2}; double array[KEYS_MAX][FIELD_MAX]; array[1][FIELD1] = 1.0; array[1][FIELD2] = 2.0; 然后,我将数据打印到KEYS\u MAX行和FIELD\u MAX列中的文件中。为了以后知道这些列的内容,我想打印一个标题行 # KEY F

我经常在C中使用
enum
来访问带有数字数据的数组元素,例如

#define KEYS_MAX 1
#define FIELD_MAX 2

enum {FIELD1=0, FIELD2};

double array[KEYS_MAX][FIELD_MAX];
array[1][FIELD1] = 1.0; array[1][FIELD2] = 2.0;
然后,我将数据打印到
KEYS\u MAX
行和
FIELD\u MAX
列中的文件中。为了以后知道这些列的内容,我想打印一个标题行

# KEY FIELD1 FIELD2
1 1.0 2.0
我希望有一个在运行时正确执行此操作的例程,即使我只通过更改
enum
来更新代码。也就是说,我如何使用C代码打印标题行,以及可能使用宏打印标题行,而不依赖于
enum
的更新


我发现了这个:,但我更喜欢同样适用于英特尔编译器的东西。

你可以玩一些预处理器的把戏。例如,在GCC源代码树实现中,您可能会受到
GCC/tree.def
文件的启发

因此,您可能有一个文件,例如
myenum.def
,其中包含以下内容

MYENUM(Pink)
MYENUM(Red)
MYENUM(Ivory)
然后,您可以使用如下代码定义枚举

enum my_enum {
#define MYENUM(Name) Name,
#include "myenum.def"
#undef MYENUM
};
(您可能希望将
None_
放在上面的
#include
之前,并将
Last_
放在后面)

然后你可以有一个枚举到字符串的转换器,例如

const char* myenum_to_string(enum my_enum en) {
  switch(en) {
#define MYENUM(Name) case Name: return #Name;
#include "myenum.def"
#undef MYENUM
  default: return NULL; /* should not happen */
  }
}
enum myenum string_to_my_enum (const char*str) {
#define MYENUM(Name) if (!strcmp(str, #Name)) return Name;
#include "myenum.def"
#undef MYENUM
  else abort ();
}
您可能有一个字符串到枚举的转换器,例如

const char* myenum_to_string(enum my_enum en) {
  switch(en) {
#define MYENUM(Name) case Name: return #Name;
#include "myenum.def"
#undef MYENUM
  default: return NULL; /* should not happen */
  }
}
enum myenum string_to_my_enum (const char*str) {
#define MYENUM(Name) if (!strcmp(str, #Name)) return Name;
#include "myenum.def"
#undef MYENUM
  else abort ();
}
所有这些都是常见的做法,与特定的编译器无关(它应该与
gcc
clang
tcc
icc
或任何符合C99的编译器一起使用)


此外,如果你有一个很大的代码库(你不能用最近的
gcc
编译),其中有数百个
enum
,你不想为每一个都玩这样的把戏,你可以开发一个gcc插件或扩展(例如)使用代码的GCC内部的内部表示,仅从
enum
声明生成类似的C代码。如果您正在编写一个新软件,或者您非常了解自己的软件库,则可以使用类似的技巧替换
enum
代码。

您可以使用一些预处理器技巧。例如,在GCC源代码树实现中,您可能会受到
GCC/tree.def
文件的启发

因此,您可能有一个文件,例如
myenum.def
,其中包含以下内容

MYENUM(Pink)
MYENUM(Red)
MYENUM(Ivory)
然后,您可以使用如下代码定义枚举

enum my_enum {
#define MYENUM(Name) Name,
#include "myenum.def"
#undef MYENUM
};
(您可能希望将
None_
放在上面的
#include
之前,并将
Last_
放在后面)

然后你可以有一个枚举到字符串的转换器,例如

const char* myenum_to_string(enum my_enum en) {
  switch(en) {
#define MYENUM(Name) case Name: return #Name;
#include "myenum.def"
#undef MYENUM
  default: return NULL; /* should not happen */
  }
}
enum myenum string_to_my_enum (const char*str) {
#define MYENUM(Name) if (!strcmp(str, #Name)) return Name;
#include "myenum.def"
#undef MYENUM
  else abort ();
}
您可能有一个字符串到枚举的转换器,例如

const char* myenum_to_string(enum my_enum en) {
  switch(en) {
#define MYENUM(Name) case Name: return #Name;
#include "myenum.def"
#undef MYENUM
  default: return NULL; /* should not happen */
  }
}
enum myenum string_to_my_enum (const char*str) {
#define MYENUM(Name) if (!strcmp(str, #Name)) return Name;
#include "myenum.def"
#undef MYENUM
  else abort ();
}
所有这些都是常见的做法,与特定的编译器无关(它应该与
gcc
clang
tcc
icc
或任何符合C99的编译器一起使用)


此外,如果你有一个很大的代码库(你不能用最近的
gcc
编译),其中有数百个
enum
,你不想为每一个都玩这样的把戏,你可以开发一个gcc插件或扩展(例如)使用代码的GCC内部的内部表示,仅从
enum
声明生成类似的C代码。如果您正在编写一个新软件,或者您非常了解自己的软件基础,那么可以使用类似的技巧替换
enum
代码。

它不是特定于GCC的,但是GCC的实现使用了这些技巧。其他一些自由软件也使用它(可能是Gtk,也可能是Linux内核的一些子系统)。我的灵感来自于gcc的
gcc/tree.def
文件,我碰巧知道这个文件。唯一的gcc特有的技巧是编写一个MELT扩展来自动生成这样的代码(来自gcc编译器构建的抽象语法树),不使用我建议的预处理器技巧。这与中描述的机制本质上是同构的,之前也提到过(仅举两例)。这并不是说你不知道这项技术,也不是说你没有从其他渠道了解到这项技术。这不是特定于GCC的,但是GCC的实现使用了这些技巧。其他一些自由软件也使用它(可能是Gtk,也可能是Linux内核的一些子系统)。我的灵感来自于gcc的
gcc/tree.def
文件,我碰巧知道这个文件。唯一的gcc特有的技巧是编写一个MELT扩展来自动生成这样的代码(来自gcc编译器构建的抽象语法树),不使用我建议的预处理器技巧。这与中描述的机制本质上是同构的,之前也提到过(仅举两例)。这并不意味着你不知道这项技术,也不意味着你没有从其他渠道了解到这项技术。