我试图简化数组的声明,但遇到了我正在使用的预处理器的问题.我的初始代码如下所示:
#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 )
};
Run Code Online (Sandbox Code Playgroud)
当然,构建失败,错误消息为"错误:'#'后面没有宏参数".这里解释了这个原因(为什么编译器抱怨这个宏声明)
基本上,我试图避免将数组声明为如下,这确实有效:
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
};
Run Code Online (Sandbox Code Playgroud)
该列表可能相当长,并根据项目的构建类型而有所不同.我曾尝试过使用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 )
};
Run Code Online (Sandbox Code Playgroud)
使用来运行gcc -std=c11 -Wall -E
,并仅显示MyList
定义:
static const MyTypedef_t MyList[] =
{
{ 78723649 , 1 }
{ 2347602 , 3 }
};
Run Code Online (Sandbox Code Playgroud)
您可以通过使用宏中的任何第二个值来执行相同的操作#define ID_x
,只要有一个即可。实际参数可以添加到中REQ_ENTRY
。但这需要一些额外的杂耍。
遗憾的是,该defined
运算符仅在#if
and的上下文中可用#ifelse
,而不适用于宏扩展。就目前而言,我同意rici关于各种丑陋的解决方案。
这是一个解决方案,需要将定义的值用括号括起来。然后,您可以使用 ID 作为常规值,也可以将其传递给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)
};
Run Code Online (Sandbox Code Playgroud)
这将产生:
static const MyTypedef_t MyList[] = {
{(27), 1},
{(28), 3},
{(29), 4},
};
Run Code Online (Sandbox Code Playgroud)
您还可以DEF
在代码中使用宏,它将被扩展为 0 或 1:
printf("ID_1 is %s.\n", DEF(ID_1) ? "defined" : "undefined");
Run Code Online (Sandbox Code Playgroud)