【问题标题】:force unused parameter for macro强制宏的未使用参数
【发布时间】:2020-02-24 10:11:12
【问题描述】:

简单的想法:

我正在使用 X-macros 来定义命令列表结构并声明命令回调。

#include <stdio.h>
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>

#define COMMAND_LIST(X) \
        X(toto_all) \
        X(help) \
        //end of list

typedef void (*callback_t)(int a, int b);

typedef struct 
{
    char * name;    
    callback_t callback;
}command_t;


#define CALLBACK_DEC(COMMAND_NAME)  void _##COMMAND_NAME(int a, int b);
COMMAND_LIST(CALLBACK_DEC)

#define COMMAND_DEF(COMMAND_NAME)  { #COMMAND_NAME, & _##COMMAND_NAME },
static command_t commands[] =
{
  COMMAND_LIST(COMMAND_DEF)
};

#define COMMAND(COMMAND_NAME,CODE)          void _##COMMAND_NAME(int A, int B) {  CODE  }

COMMAND(toto_all,
    printf("helloworld\n");
)

COMMAND(help,
    printf("help!\n");
)

int main()
{
    commands[0].callback(1,2);
    commands[1].callback(1,2);

    return 0;
}

它有效。

你好世界
帮忙!


添加一些参数:

如果将第一个命令列表更改为此(通过添加参数)

#define COMMAND_LIST(X) \
        X(toto_all,         1,      3,      5) \
        X(help,             0,      0,      0) \
        //end of list

typedef struct 
{
    callback_t callback;
    char * name;  
    int arg_min; 
    int arg_max;
    int arg_num;
}command_t;

然后,在运行它时,我收到以下错误:

macro "CALLBACK_DEC" passed 4 arguments, but takes just 1

我必须使用命令列表定义(命令声明)的所有参数:

#define COMMAND_DEF(COMMAND_NAME, ARG_MIN, ARG_MAX, ARG_MAX, ARG_NUM)  (command_t){ #COMMAND_NAME, & _##COMMAND_NAME, ARG_MIN, ARG_MAX, ARG_NUM},

但是现在将它用于回调声明非常棘手......

这个 X-macro 有没有巧妙的方法来避免这个错误?


想到了屏蔽未使用参数的非宏方式:

使用(void)param;, 这给了丑陋的

#define CALLBACK_DEC(COMMAND_NAME, ARG_MIN, ARG_MAX, ARG_NUM) void _##COMMAND_NAME(int a, int b); void(ARG_MIN); void(ARG_MAX);  void(ARG_NUM)

这不起作用......我很奇怪:

main.c:27:20: error: expected identifier or ‘(’ before numeric constant
         X(toto_all,0,0,0) \

我认为还有另一种方式:

也许使用类似的东西......

#define COMMAND_LIST(X,Y) \
        X(Y(toto_all,         0,      0,      0)) \
        X(Y(help,             0,      0,      0)) \
        //command name,    arg min, arg max, arg num, string?
        //end of list

typedef void (*callback_t)(int a, int b);

typedef struct 
{
    char * name;    
    callback_t callback;
}command_t;

#define GET_ONLY_NAME(COMMAND_NAME1, ARG_MIN, ARG_MAX, ARG_NUM) COMMAND_NAME1
#define CALLBACK_DEC(COMMAND_NAME)  void _##COMMAND_NAME(int a, int b);
COMMAND_LIST(CALLBACK_DEC,GET_ONLY_NAME);
#undef CALLBACK_DEC

#define GET_FULL_LIST(X) X
#define COMMAND_DEF(COMMAND_NAME, ARG_MIN, ARG_MAX, ARG_NUM)  (command_t){ #COMMAND_NAME, & _##COMMAND_NAME, ARG_MIN, ARG_MAX, ARG_NUM},
static command_t commands[] =
{
  COMMAND_LIST(COMMAND_DEF,GET_FULL_LIST)
};
#undef COMMAND_DEF

但我还是得到了以下奇怪的错误,扩展有问题但我看不到在哪里...

main.c:27:31: error: expected ‘)’ before numeric constant
         X(Y(toto_all,         0,      0,      0)) \

也许真相在别处...... :)

有什么提示吗?

【问题讨论】:

  • “它有效”的版本不起作用。您在这里有一个分号:COMMAND_LIST(CALLBACK_DEC);,但也在它上面的宏声明中。此外,您不能使用复合文字来初始化文件范围变量,因为这不是常量表达式。 (只要去掉复合文字符号就可以了。)编译代码需要哪个编译器和什么非标准设置?
  • 只需复制粘贴第一个代码,您就会看到它有效:onlinegdb.com/SyABNE-NL
  • 好吧,默认 GNU C。可能想养成使用 -std=c11 -pedantic-errors 编译的习惯,你会发现 GNU C 版本隐藏的各种错误和语法错误。
  • thanx,已在帖子中更正。这并没有回答这个问题:o)

标签: c macros x-macros


【解决方案1】:

这是整个 X 宏的一个问题 - 您必须编写一个接受所有参数的宏,即使您只使用了一些参数。

在您的情况下,您将特定宏作为参数传递给列表,因此您可以在那里增加一些灵活性。使用可变参数宏可能会解决问题。你应该可以这样做:

#define COMMAND_DEF(COMMAND_NAME, ...)  { #COMMAND_NAME, & _##COMMAND_NAME },
...
COMMAND_LIST(COMMAND_DEF)

您只显式命名此特定宏感兴趣的参数,然后让其余参数进入 ... 部分,然后将其忽略。

然而,这确实在数据中建立了依赖关系,因为它只允许您从左到右扩展参数,可以这么说。所以对于

X(toto_all,         1,      3,      5,      "-")

您可以编写仅使用toto_alltoto_all1 的宏,但您不能编写仅使用例如13 的宏。对于这种特殊情况,我相信您仍然需要命名所有宏参数。

另一种选择是自记录代码:

#define COMMAND_DEF(COMMAND_NAME, ignored1, FOO, ignored2, ignored3) \
/* do stuff with COMMAND NAME and FOO only */

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-28
    • 1970-01-01
    相关资源
    最近更新 更多