7

オープンソースプロジェクトtigのコードサンプルを参照しています。これは素晴らしいツールです!

file: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何度もあり、混乱を招いています。少なくとも私にとっては。そうするのには十分な理由があるかもしれません。マクロを使用してコード内の列挙型/構造体の定義を非表示にする実際の理由は何ですか?

4

3 に答える 3

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

このように、列挙型の値のセットは1回だけ書き込まれ、自動的に列挙型とそれを処理するいくつかのメソッドの両方がこのセットと同期されます。

于 2013-02-13T13:02:02.967 に答える
1

リクエストのリストの重複を避けるためです。そのリストは、の定義を1か所で維持するだけでREQ_INFOよく、列挙とデータ構造は、との適切な定義によってそのリストから自動的に生成されREQ_GROUPますREQ_

これらのマクロがないと、列挙とデータ構造を別々に維持する必要があり、それらの一貫性を保つように注意して、より多くの作業とエラーの範囲を増やす必要があります。

于 2013-02-13T13:10:50.943 に答える
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 >
};

他の回答が述べたように、それは主に複数の構造/列挙子の同期を維持するために行われます。

于 2013-02-13T13:12:56.480 に答える