同时定义数组和符号索引

时间:2009-04-27 17:57:27

标签: c syntax

我正在尝试一种聪明的方法(在C中)创建一个字符串数组,以及数组索引的符号名称(枚举或#define),在一个结构中便于维护。类似的东西:

const char * strings [] = {     M(STR_YES,“是”),     M(STR_NO,“不”),     M(STR_MAYBE,“也许”) };

其中结果相当于:

const char * strings [] = {“yes”,“no”,“maybe”}; 枚举索引{STR_YES,STR_NO,STR_MAYBE}; (或#define STR_YES 0等)

但是我在这种情况下为如何构造M宏绘制了一个空白。

任何聪明的想法?

3 个答案:

答案 0 :(得分:6)

clang编译器源中使用的一种技术是创建包含这样的列表的.def文件,该文件的设计类似于C文件,可以轻松维护而无需触及使用它的其他代码文件。例如:

#ifndef KEYWORD
#define KEYWORD(X)
#endif
#ifndef LAST_KEYWORD
#define LAST_KEYWORD(X) KEYWORD(X)
#endif

KEYWORD(return)
KEYWORD(switch)
KEYWORD(while)
....
LAST_KEYWORD(if)

#undef KEYWORD
#undef LAST_KEYWORD

现在,它做的是包括这样的文件:

/* some code */
#define KEYWORD(X) #X, 
#define LAST_KEYWORD(X) #X

const char *strings[] = { 
#include "keywords.def"
};

#define KEYWORD(X) kw_##X, 
#define LAST_KEYWORD(X) kw_##X

enum { 
#include "keywords.def"
};

在你的情况下,你可以做类似的事情。如果您可以使用STR_yesSTR_no,...作为枚举器名称,则可以使用与上述相同的方法。否则,只需传递宏两件事。一个小写名称和一个大写名称。然后你可以将上面想要的那个字符串化。

答案 1 :(得分:4)

这是使用代码生成的好地方。使用perl,php等语言生成.h文件。

答案 2 :(得分:0)

不需要将其放入特定的.def文件中;仅使用预处理器是完全可能的。我通常会定义一个名为...LIST的列表,其中每个元素都包含在...LIST_ELEMENT中。根据我将使用的列表,我将使用逗号分隔除最后一个条目(最简单),或者在一般情况下,可以在每次使用时单独选择分隔符。例如:

#include <string.h>

#define DIRECTION_LIST \
DIRECTION_LIST_ELEMENT( up,    DIRECTION_LIST_SEPARATOR ) \
DIRECTION_LIST_ELEMENT( down,  DIRECTION_LIST_SEPARATOR ) \
DIRECTION_LIST_ELEMENT( right, DIRECTION_LIST_SEPARATOR ) \
DIRECTION_LIST_ELEMENT( left,  NO_COMMA )

#define COMMA ,
#define NO_COMMA /**/

#define DIRECTION_LIST_ELEMENT(elem, sep) elem sep
#define DIRECTION_LIST_SEPARATOR COMMA
typedef enum {
    DIRECTION_LIST
} direction_t;
#undef DIRECTION_LIST_ELEMENT
#undef DIRECTION_LIST_SEPARATOR

#define DIRECTION_LIST_ELEMENT(elem, sep) void (*move_ ## elem)(struct object_s * object);
#define DIRECTION_LIST_SEPARATOR NO_COMMA
typedef struct object_s {
    char *name;
    // ...
    DIRECTION_LIST
} object_t;
#undef DIRECTION_LIST_ELEMENT
#undef DIRECTION_LIST_SEPARATOR

static void move(object_t *object_p, const char * direction_string)
{
    if (0) {
    }
#define DIRECTION_LIST_SEPARATOR NO_COMMA
#define DIRECTION_LIST_ELEMENT(elem, sep) \
    else if (strcmp(direction_string, #elem) == 0) { \
        object_p->move_ ## elem(object_p); \
    }
    DIRECTION_LIST
#undef DIRECTION_LIST_ELEMENT
#undef DIRECTION_LIST_SEPARATOR
}