是否可以检查X宏定义的列表中的条目是否存在?给定下面的示例代码,我希望#if defined(GEORGE)条件为true。
编辑:当然,不做显式的#define GEORGE。我希望有一种方法来检查列表中的条目(在预处理器中),我只想在列表中进行声明。这可能是不可能的,但我想我会问。
谢谢!

#include <stdio.h>

#define NAMES \
X( JOHN, "John Adams" ) \
X( GEORGE, "George Washington" ) \
X( ABRAHAM, "Abraham Lincoln ")

#define X(_id, _name)    _id,
typedef enum {
    NAMES
} names_e;
#undef X

typedef struct {
    char *name;
} names_t;

#define X(_id, _name)    [_id] = { .name = _name },
static names_t const names[] = {
    NAMES
};
#undef X

int main(void) {
    int i;

    for (i=0; i < sizeof(names)/sizeof(names[0]); i++) {
        printf("%s\n", names[i].name);
    }

    printf("names[ABRAHAM] = %s\n", names[ABRAHAM].name);

#if defined(GEORGE)
    printf("names[GEORGE] = %s\n", names[GEORGE].name);
#endif

    return 0;
}

输出
John Adams
George Washington
Abraham Lincoln
names[ABRAHAM] = Abraham Lincoln

最佳答案

您可以尝试使用预处理器模式匹配器。这个概念只需要一个带间接寻址的SECOND宏;GLUE可以在以下位置插入任意前缀:

#define GLUE(A,B) GLUE_I(A,B)
#define GLUE_I(A,B) A##B

#define SECOND(...) SECOND_I(__VA_ARGS__,,)
#define SECOND_I(A,B,...) B

…对于只包含“伪标识符”的X宏“列”:
#define NAMES \
X( JOHN, "John Adams" ) \
X( GEORGE, "George Washington" ) \
X( ABRAHAM, "Abraham Lincoln ")

……你可以这样做:
#define X(ID_, NAME_) SECOND(GLUE(SEARCH_FOR_,ID_),+0)
#define SEARCH_FOR_GEORGE ,+1
#if NAMES
printf("names[GEORGE] = %s\n", names[GEORGE].name);
#endif
#undef SEARCH_FOR_GEORGE
#define SEARCH_FOR_THOMAS ,+1
#if NAMES
#error Dewey wins!
#endif
#undef SEARCH_FOR_THOMAS
#undef X

这是因为SECOND间接扩展到第二个参数;因此默认情况下SECOND(GLUE(SEARCH_FOR,ID_),+0)将扩展到+0;并且+0的任何链都是有效的假表达式。但由于扩展是间接的,第一个参数是粘贴的标记,因此如果将粘贴的标记SEARCH_FOR_GEORGE定义为使用逗号进行扩展,则逗号后的表达式将成为新的第二个参数。(问我是否需要这个来处理微软VS预处理器;这需要一个小小的调整)。

关于c - 检查C预处理程序列表中是否存在条目,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49000189/

10-11 22:54
查看更多