问题描述
我试图简化数组的声明,但是遇到了我使用的预处理器的问题.我的初始代码如下:
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,但我想我也会遇到同样的问题.我希望有人能看到一种创建预处理器宏的方式,从而可以实现原始的Sugar语法?任何见解都将不胜感激.
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 和序列,则可以这样解决:
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.
这篇关于预处理器由于以下原因而失败--'#'后没有宏参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!