预处理器失败,因为 – ‘#’后面没有宏参数

我试图简化数组的声明,但遇到了我正在使用的预处理器的问题。 我的初始代码如下所示:

#define REQ_ENTRY(parm_1, parm_2) \ #if defined(parm_1) \ { parm_1, parm_2 }, \ #endif typedef struct { int parm1, parm2; } MyTypedef_t; static const MyTypedef_t MyList[] = { REQ_ENTRY( ID_1, 1 ) REQ_ENTRY( ID_2, 2 ) REQ_ENTRY( ID_3, 3 ) REQ_ENTRY( ID_4, 4 ) REQ_ENTRY( ID_5, 5 ) }; 

当然,构建失败,错误消息为“错误:’#’后面没有宏参数”。 这里解释了这个原因( 为什么编译器抱怨这个宏声明 )

基本上,我试图避免将数组声明为如下,这确实有效:

 static const MyTypedef_t MyList[] = { #if defined (ID_1) { ID_1, 1 }, #endif #if defined (ID_2) { ID_2, 2 }, #endif #if defined (ID_3) { ID_3, 3 }, #endif #if defined (ID_4) { ID_4, 4 }, #endif #if defined (ID_5) { ID_5, 5 }, #endif }; 

该列表可能相当长,并根据项目的构建类型而有所不同。 我曾尝试过使用x-macros,但我想我会遇到同样的问题。 我希望有人可能会看到一种方法来创建预处理器宏,以便我可以实现原始的糖语法? 非常感谢任何见解。

没有很好的清洁解决方案。 但是有各种丑陋的解决方案。

如果您不介意在宏定义中同时包含id序列 ,可以像这样解决:

 #define CONCAT2(x,y) x##y #define CONCAT(x,y) CONCAT2(x,y) #define REQ_ENTRY_YES(p1, p2) { p1 , p2 } #define REQ_ENTRY_NO(p1) #define IS_PAIR_HELPER(a, b, c, ...) c #define IS_PAIR(...) IS_PAIR_HELPER(__VA_ARGS__, YES, NO) #define REQ_ENTRY(pair) CONCAT(REQ_ENTRY_, IS_PAIR(pair))(pair) #define ID_1 78723649, 1 #define ID_3 2347602, 3 typedef struct { int parm1, parm2; } MyTypedef_t; static const MyTypedef_t MyList[] = { REQ_ENTRY( ID_1 ) REQ_ENTRY( ID_2 ) REQ_ENTRY( ID_3 ) REQ_ENTRY( ID_4 ) REQ_ENTRY( ID_5 ) }; 

使用-std=c11 -Wall -E运行gcc,并仅显示MyList定义:

 static const MyTypedef_t MyList[] = { { 78723649 , 1 } { 2347602 , 3 } }; 

你可以通过在#define ID_x宏中使用任何第二个值来做同样的事情,只要有一个; 真实参数可以添加到REQ_ENTRY 。 但它需要一些额外的杂耍。

遗憾的是, defined运算符仅在#if#ifelse的上下文中#ifelse ,但不适用于宏扩展。 就目前而言,我同意rici关于不同丑陋的解决方案。

这是一个解决方案,要求定义的值被括号括起来。 然后,您可以将ID用作常规值,也可以将其传递给DEF ,当宏在括号中时, DEF会扩展为1,否则会扩展为0。 (这是我在这里学到的一个技巧。)

DEF宏的帮助下,您可以创建扩展或忽略给定定义的辅助宏:

 /* Auxiliary macros */ #define M_CHECK(...) M_CHECK_(__VA_ARGS__) #define M_CHECK_(a, b, ...) b #define M_IS_PAREN(x) M_CHECK(M_IS_PAREN_ x, 0) #define M_IS_PAREN_(...) 1, 1 #define M_CONCAT(a, b) M_CONCAT_(a, b) #define M_CONCAT_(a, b) a ## b /* Conditional definition macros */ #define DEF(x) M_IS_PAREN(x) #define DEF_IF_0(id, def) #define DEF_IF_1(id, def) {id, def}, #define COND_DEF(x, y) M_CONCAT(DEF_IF_, DEF(x))(x, y) /* Implementation */ #define ID_1 (27) #define ID_3 (28) #define ID_4 (29) static const MyTypedef_t MyList[] = { COND_DEF(ID_1, 1) COND_DEF(ID_2, 2) COND_DEF(ID_3, 3) COND_DEF(ID_4, 4) COND_DEF(ID_5, 5) }; 

这将产生:

 static const MyTypedef_t MyList[] = { {(27), 1}, {(28), 3}, {(29), 4}, }; 

您还可以在代码中使用DEF宏,它将扩展为0或1:

 printf("ID_1 is %s.\n", DEF(ID_1) ? "defined" : "undefined");