计算预处理器宏

时间:2011-12-28 23:22:13

标签: c macros c-preprocessor

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

#define ENUM_DEFINITIONS(F) \
  F(0, Item1) \
  F(5, Item2) \
  F(15, Item3) \
  ...
  F(63, ItemN)

然后:

enum Items {
  #define ITEM_ENUM_DEFINE(id, name) name = id,
    ENUM_DEFINITIONS(ITEM_ENUM_DEFINE)
  #undef ITEM_ENUM_DEFINE

,当扩展时,应该产生:

enum Items {
  Item1 = 0,
  Item2 = 5,
  Item3 = 15,
  ...
  ItemN = 63,
}

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

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

,当扩展时,产生:

itemNames[iter++] = "Item1";
itemNames[iter++] = "Item2";
itemNames[iter++] = "Item3";
...
itemNames[iter++] = "ItemN";

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

我见过提到非标准 COUNTER 宏,类似于 FILE LINE 宏,但我希望有一种更标准的方式。

如果有更好的方法可以在不使用宏的情况下实现这一目标,也会有兴趣听到。

5 个答案:

答案 0 :(得分: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])

编辑:感谢Raymond Chen注意到我们不必担心列表中不必要的最终逗号。 (对于使用严格的C89编译器的枚举问题,我一直在误解问题,如Is the last comma in C enum required?中所述。)

答案 1 :(得分:4)

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

enum itemscounter  { 
  #define ITEM_ENUM_DEFINE(id, name) name##counter,
    ENUM_DEFINITIONS(ITEM_ENUM_DEFINE) 
  #undef ITEM_ENUM_DEFINE 
 TOTAL_ITEMS
};

答案 2 :(得分:2)

  

如果有更好的方法可以在不使用宏的情况下实现这一目标,也会有兴趣听到。

您可以随时使用ruby或python等脚本语言为您生成.c和.h文件。如果做得好,可以将脚本集成到Makefile中。

答案 3 :(得分:1)

我知道这不是一个完整的答案。 你可以围绕这样的东西创建一个宏。

#include <stdio.h>

const char * array[] = {
  "arr1", "arr2", "arr3", "arr4"
};

int main (int argc, char **argv)$
{
  printf("%d\n", sizeof(array)/sizeof(const char *));
}

如果你可以修改你的enum所以它有连续的元素你可以这样做(来自Boost)

enum { A=0,B,C,D,E,F,N };
const char arr[N]; // can contain a character for each enum value

答案 4 :(得分:0)

见建议Mu Dynamics 'Enums, Strings and Laziness';这些至少与你所追求的有关。

否则,请查看Boost Preprocessor集合(可用于C预处理器以及C ++预处理器)。