通过宏定义Enum / Struct有什么需要?

时间:2013-02-13 12:49:24

标签: c++ c macros struct enums

我指的是来自开源项目 tig 的代码示例。这是一个很棒的工具!

文件:tig.c

我很难找到定义请求枚举的理由,如下所示:

enum request {
#define REQ_GROUP(help)
#define REQ_(req, help) REQ_##req

        /* Offset all requests to avoid conflicts with ncurses getch values. */
        REQ_UNKNOWN = KEY_MAX + 1,
        REQ_OFFSET,
        REQ_INFO,

        /* Internal requests. */
        REQ_JUMP_COMMIT,

#undef  REQ_GROUP
#undef  REQ_
};

甚至结构......

static const struct request_info req_info[] = {
#define REQ_GROUP(help) { 0, NULL, 0, (help) },
#define REQ_(req, help) { REQ_##req, (#req), STRING_SIZE(#req), (help) }
        REQ_INFO
#undef  REQ_GROUP
#undef  REQ_
};

可以看出REQ_GROUP多次被#defined引起混淆..至少对我而言。我知道可能有一个很好的理由这样做..使用宏隐藏代码中的枚举/结构定义的实际原因是什么?

3 个答案:

答案 0 :(得分:7)

当在同一数据源上使用不同的处理时,这通常会失效。

例如,您可以这样做:

#define MY_LIST X(Elem1) X(Elem2) X(Elem3)

然后:

enum MyEnum {
# define X(e) e,

  MY_LIST

  Last

# undef X
};

在这种情况下,使用MY_LIST当前定义展开X

现在,在同一个文件中,我还可以使用MY_LIST创建to_string方法

char const* to_string(MyEnum e) {
    switch(e) {
#       define X(e) case e: return #e;

        MY_LIST

        case Last: return "Last";

#       undef X
    }
    return 0;
} // to_string

这样,enum的值集只能写一次,并且enum和处理它的一些方法都会自动与这个集保持同步。

答案 1 :(得分:1)

这是为了避免重复请求列表。该列表只需要在一个地方维护,REQ_INFO的定义,并通过REQ_GROUPREQ_的适当定义从该列表自动生成枚举和数据结构。

如果没有这些宏,枚举和数据结构必须单独维护,注意保持它们彼此一致,涉及更多的工作和更多的错误范围。

答案 2 :(得分:1)

您错过了同一档案中的重要定义:

#define REQ_INFO \
REQ_GROUP("View switching") \
VIEW_INFO(VIEW_REQ), \
\
REQ_GROUP("View manipulation") \
REQ_(ENTER, "Enter current line and scroll"), \
REQ_(NEXT, "Move to next"), \
REQ_(PREVIOUS, "Move to previous"), \
< output omitted as it is too long >

因此,例如,您展示的结构扩展为:

static const struct request_info req_info[] = {
   { 0, NULL, 0, "View switching" },
   < VIEW_INFO also expands to some long structure that was ommited here >
   { 0, NULL, 0, "View manipulation" },
   { REQ_ENTER, ENTER, STRING_SIZE("ENTER"), "Enter current line and scroll"},
   { REQ_NEXT, NEXT, STRING_SIZE("NEXT"), "Move to next"}
   < and so on >
};

正如其他提到的答案,主要是为了保持多个结构/枚举器同步。