2011-12-28 91 views
8

我有这样的宏代码,这让我既定义一个ç枚举和使用一种构建串列举名称的列表。它防止我必须重复枚举器名称(并可能为大型列表引入错误)。计数预处理宏

#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宏,类似于FILELINE宏提及,但我希望有一个更标准的方式。

也将是兴趣听是否有更好的方式来实现这一目标,而不必使用宏。

+0

为什么你需要'enum'和字符串数组? – Philip 2011-12-29 06:21:24

+0

它似乎在我的工作中很常见。一个例子是枚举状态的状态机,前端GUI显示当前状态的名称。它只需定义一次便于使用,并且使希望添加新状态的其他开发人员更容易。 – Eyal 2011-12-29 18:39:09

回答

7

下面应该工作:

#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]) 

编辑:谢谢陈雷蒙德为指出,我们不必担心在列表中不必要的最后一个逗号。 (我一直误以为有严格的C89编译器的枚举问题,如Is the last comma in C enum required?。)

+1

你不需要吃尾随的逗号。尾随的逗号是合法的,并被忽略。 – 2011-12-28 23:51:27

+0

关于最后一个不必要的逗号,我似乎记得SGI Irix编译器会发出一个不可压制的警告,这迫使我总是忽略它。 – 2011-12-29 00:22:17

2

如果有更好的方法来实现这一点,而不必使用宏,也会有兴趣听到。

您可以随时使用脚本语言(例如ruby或python)为您生成.c和.h文件。如果你做得很好,你可以将你的脚本整合到你的Makefile中。

+1

我一般都不喜欢将其他语言添加到构建要求的方法。 – Alex 2011-12-28 23:53:57

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 *)); 
} 

如果你可以修改你的枚举所以它具有连续的元素,你可以做某事像这样(与Boost)

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

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

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

我接受了上面的答案,但认为这也是一个相当不错的(和聪明的)方法。谢谢! – Eyal 2011-12-29 18:33:59