计算预处理器宏

Eya*_*yal 9 c macros c-preprocessor

我有这个宏代码,它允许我使用一个构造将C枚举和枚举名称列表定义为字符串.它阻止我不得不复制枚举器名称(并可能为大型列表引入错误).

#define ENUM_DEFINITIONS(F) \
  F(0, Item1) \
  F(5, Item2) \
  F(15, Item3) \
  ...
  F(63, ItemN)
Run Code Online (Sandbox Code Playgroud)

然后:

enum Items {
  #define ITEM_ENUM_DEFINE(id, name) name = id,
    ENUM_DEFINITIONS(ITEM_ENUM_DEFINE)
  #undef ITEM_ENUM_DEFINE
Run Code Online (Sandbox Code Playgroud)

当扩展时,应该产生:

enum Items {
  Item1 = 0,
  Item2 = 5,
  Item3 = 15,
  ...
  ItemN = 63,
}
Run Code Online (Sandbox Code Playgroud)

在实现文件中,我有这个代码:

const char* itemNames[TOTAL_ITEMS];
int iter = 0;

#define ITEM_STRING_DEFINE(id, name) itemNames[iter++] = #name;
  ENUM_DEFINITIONS(ITEM_STRING_DEFINE)
#undef ITEM_STRING_DEFINE
Run Code Online (Sandbox Code Playgroud)

当扩展时,产生:

itemNames[iter++] = "Item1";
itemNames[iter++] = "Item2";
itemNames[iter++] = "Item3";
...
itemNames[iter++] = "ItemN";
Run Code Online (Sandbox Code Playgroud)

我想知道我以这种方式创建了多少枚举项,并能够将它传递给编译时数组.在上面的示例中,这将在编译时确定TOTAL_ITEMS = N. 是否可以用这种方式计算宏调用?

我已经看到过提到一个非标准的COUNTER宏,类似于FILELINE宏,但我希望有更标准的方法.

也有兴趣听听是否有更好的方法来实现这一点,而不必使用宏.

Jos*_*sey 8

以下应该有效:

#define ITEM_STRING_DEFINE(id, name) #name, // note trailing comma
const char *itemNames[] = {
  ENUM_DEFINITIONS(ITEM_STRING_DEFINE)
};

#define TOTAL_ITEMS (sizeof itemNames / sizeof itemNames[0])
Run Code Online (Sandbox Code Playgroud)

编辑:感谢Raymond Chen注意到我们不必担心列表中不必要的最终逗号.(对于使用严格C89编译器的枚举问题,我一直在误解这个问题,因为是否需要使用C enum中的最后一个逗号?)


Ray*_*hen 6

您可以使用相同的技术来计算调用次数。

enum itemscounter  { 
  #define ITEM_ENUM_DEFINE(id, name) name##counter,
    ENUM_DEFINITIONS(ITEM_ENUM_DEFINE) 
  #undef ITEM_ENUM_DEFINE 
 TOTAL_ITEMS
};
Run Code Online (Sandbox Code Playgroud)