问题描述
我正在尝试简化数组的声明,但遇到了我正在使用的预处理器的问题.我的初始代码如下所示:
I am trying to simplify the declaration of an array, but ran into an issue with the preprocessors that I am using. My initial code looks like the following:
#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 )
};
构建失败,当然,错误消息错误:'#'后面没有宏参数".此处解释了其原因(为什么编译器会抱怨此宏声明)
The build fails, of course, with the error message of "error: '#' is not followed by a macro parameter". The reason for this is explained here (Why compiler complain about this macro declaration)
基本上,我试图避免将数组声明如下,这确实有效:
Basically, I am trying to avoid declaring the array as the follows, which does work:
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,但我想我会遇到同样的问题.我希望有人可能会看到一种创建预处理器宏的方法,以便我可以实现原始的糖语法?非常感谢任何见解.
The list can be rather long and vary depending upon the build type of the project. I have tried thinking of using x-macros, but I think I would have the same issue. I am hoping someone might see a way of creating the preprocessor macros in such a way that I could achieve the original sugar syntax? Any insight is greatly appreciated.
推荐答案
没有很好的干净解决方案.但也有各种丑陋的解决方案.
There is no nice clean solution. But there are solutions of varying ugliness.
如果你不介意在宏定义中同时包含id和sequence,可以这样解决:
If you don't mind including both the id and the sequence in the macro definition, it can be solved like this:
#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
定义:
Run through gcc with -std=c11 -Wall -E
, and showing only the MyList
definition:
static const MyTypedef_t MyList[] =
{
{ 78723649 , 1 }
{ 2347602 , 3 }
};
您可以通过在 #define ID_x
宏中使用 any 第二个值来做同样的事情,只要有一个即可;真正的参数可以添加到REQ_ENTRY
.但这需要一些额外的杂耍.
You can do the same thing by using any second value in the #define ID_x
macros, as long as there is one; the real parameters can be added to REQ_ENTRY
. But it takes some extra juggling.
这篇关于由于 - '#' 后面没有宏参数,预处理器失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!