C 强制宏的未使用参数 简单的想法:

C 强制宏的未使用参数 简单的想法:,c,macros,x-macros,C,Macros,X Macros,我使用X宏定义命令列表结构并声明命令回调 #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 v

我使用X宏定义命令列表结构并声明命令回调

#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;
}
然后,在运行它时,我得到以下错误:

macro "CALLBACK_DEC" passed 4 arguments, but takes just 1
我必须使用命令列表定义(命令声明)的所有参数:

但是现在在回调声明中使用它是相当棘手的

此X宏是否有一种巧妙的方法来避免此错误?


我想到了屏蔽未使用参数的非宏方法: 这是通过使用
(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)) \
也许真相就在别处……:)


有什么提示吗?

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

在您的例子中,您可以将特定宏作为参数传递到列表中,因此可以在列表中添加一些灵活性。使用可变宏可能会解决这个问题。您应该能够这样做:

#define COMMAND_DEF(COMMAND_NAME, ...)  { #COMMAND_NAME, & _##COMMAND_NAME },
...
COMMAND_LIST(COMMAND_DEF)
在这里,您只显式地命名此特定宏感兴趣的参数,然后让其余的参数进入
部分,然后忽略该部分

但是,这确实在数据中建立了依赖关系,因为它只允许从左到右展开参数。所以

X(toto_all,         1,      3,      5,      "-")
您可以编写只使用
toto\u all
toto\u all
1
的宏,但无法编写只使用例如
1
3
的宏。对于这种特殊情况,我相信您仍然需要命名所有宏参数

另一种选择是自文档化代码:

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

“它有效”的版本不起作用。这里有一个分号:
COMMAND\u LIST(CALLBACK\u DEC)但也在上面的宏声明中。此外,不能使用复合文字来初始化文件范围变量,因为它不是常量表达式。(只要去掉复合文字符号,它就可以工作了。)编译代码需要哪个编译器以及什么非标准设置?只需复制粘贴第一个代码,您就会看到它是有效的:好的,那么默认GNU C。您可能想养成使用
-std=c11-pedantic errors
编译的习惯,并且您会发现GNU C版本隐藏的各种错误和语法错误。thanx已在帖子中更正。但这并不能回答这个问题:o)
X(toto_all,         1,      3,      5,      "-")
#define COMMAND_DEF(COMMAND_NAME, ignored1, FOO, ignored2, ignored3) \
/* do stuff with COMMAND NAME and FOO only */