我有这个宏代码,它允许我使用一个构造将 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 宏,但我希望有一种更标准的方式。
如果有更好的方法可以在不使用宏的情况下实现这一目标,也会有兴趣听到。
答案 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 ++预处理器)。