本文介绍了由于 - '#' 后面没有宏参数,预处理器失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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.

如果你不介意在宏定义中同时包含idsequence,可以这样解决:

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.

这篇关于由于 - '#' 后面没有宏参数,预处理器失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-29 07:28