Kot*_*tte 6 c enums gcc c-preprocessor
我目前正在开发一个包含大量枚举的代码库.需要将enum值转换为字符串表示形式和从字符串表示形式转换值.要做到这一点,有一堆辅助宏可以在窗体上的宏上运行
#define THINGS_MAP(G, P) \
G(LAMP, P) \
G(DESK, P)
Run Code Online (Sandbox Code Playgroud)
在代码的其他地方有一些宏大致如下:
#define MK_ENUM(SYM, P) P##_##SYM,
enum { THINGS_MAP(MK_ENUM, THING) }; /* expands to { THING_LAMP, THING_DESK, } */
Run Code Online (Sandbox Code Playgroud)
我想避免更改MK_ENUM和THINGS_MAP枚举内部的调用.
但是,我现在有一个特别长的enum列表,我还需要在条目中添加一些分类.所以我在考虑做类似的事情
#define THINGS_PROP_MAP(G, P) \
G(LAMP, WOODEN, P) \
G(DESK, METALIC, P)
Run Code Online (Sandbox Code Playgroud)
但是,由于我所有的帮助器宏都需要传递两个参数,而不是三个,我在想是否可以映射某种丢弃参数的宏.这可能吗?
我正在寻找的东西是:
#define THINGS_PROP_MAP(G, P) \
G(LAMP, WOODEN, P) \
G(DESK, METALIC, P)
/* DROP_PROP should create G(LAMP, P) G(DESK, P) */
#define THINGS_MAP(G, P) DROP_PROP(THINGS_PROP_MAP)
Run Code Online (Sandbox Code Playgroud)
我有一个想法是添加一个额外的转换步骤,但我没有让它工作
#define THINGS_PROP_MAP(G, T, P) \
G(T(LAMP, WOODEN, P)) \
G(T(DESK, METALIC, P))
#define DROP_PROP(SYM, _ , P) SYM, P
#define THING_MAP(G, P) THING_PROP_MAP(G, DROP_PROP, P)
Run Code Online (Sandbox Code Playgroud)
是的,我知道这是超出宏观滥用等等:-)
您的宏很好,但您#define MK_ENUM(SYM, P) P##_##SYM,需要两个参数,例如此调用G(T(LAMP, WOODEN, P))仅使用一个参数G = MK_ENUM进行调用G,即使内部语句将扩展为LAMP, P.
要强制预处理器执行一个额外的扩展步骤并识别这LAMP, P不是单个标记,您必须添加:
#define MK_ENUM_EXPAND(...) MK_ENUM(__VA_ARGS__)
Run Code Online (Sandbox Code Playgroud)
然后使用:
enum { THING_MAP(MK_ENUM_EXPAND, THING) };
Run Code Online (Sandbox Code Playgroud)
进一步注意,您的宏不会扩展为enum { THING_LAMP, THING_DESK };,但末尾有一个逗号enum { THING_LAMP, THING_DESK, };。
完整的工作代码:
#define MK_ENUM(SYM, P) P##_##SYM,
#define MK_ENUM_EXPAND(...) MK_ENUM(__VA_ARGS__)
#define THINGS_PROP_MAP(G, T, P) \
G(T(LAMP, WOODEN, P)) \
G(T(DESK, METALIC, P))
#define DROP_PROP(SYM, _ , P) SYM, P
#define THINGS_MAP(G, P) THINGS_PROP_MAP(G, DROP_PROP, P)
enum { THINGS_MAP(MK_ENUM_EXPAND, THING) }; /* expands to { THING_LAMP, THING_DESK, } */
Run Code Online (Sandbox Code Playgroud)
要测试宏扩展,使用 gcc 和命令行参数很有用-E:
$ gcc -E srcFile.c
Run Code Online (Sandbox Code Playgroud)
因为您会收到具体的错误消息并了解出了什么问题。
如果您不想更改MK_ENUM和对枚举内部的调用,THINGS_MAP您可以执行以下操作,我只是G##S在THINGS_PROP_MAPwhereG = MK_ENUM和中连接S = _EXPAND:
#define MK_ENUM(SYM, P) P##_##SYM,
#define MK_ENUM_EXPAND(...) MK_ENUM(__VA_ARGS__)
#define THINGS_PROP_MAP(G, S, T, P) \
G##S(T(LAMP, WOODEN, P)) \
G##S(T(DESK, METALIC, P))
#define DROP_PROP(SYM, _ , P) SYM, P
#define THINGS_MAP(G, P) THINGS_PROP_MAP(G, _EXPAND, DROP_PROP, P)
enum { THINGS_MAP(MK_ENUM, THING) }; /* expands to { THING_LAMP, THING_DESK, } */
Run Code Online (Sandbox Code Playgroud)