C 预处理器宏多参数

C preprocessor macro multiple arguments

所以我有这个 'check' 宏,它有两个参数:

#define check(reg, n) ((reg >> n) & 1U)

我有这个参数列表:

#define TEST_ARGS 10, 1

代码:

check(TEST_ARGS);

预期扩张:

((10 >> 1) & 1U)

实际展开:

((10, 1 >> ) & 1U)

如何为“检查”宏定义多个参数以获得预期结果?

非常感谢。

预处理器执行文本替换(实际上它替换了标记)。所以如果

#define check(reg, n) ((reg >> n) & 1U)
#define TEST_ARGS 10, 1

然后

check(TEST_ARGS);

被预处理为:

check(10, 1,);  

第一个参数是完整的标记10,1,第二个参数是空的

简而言之,这个问题与 TEST_ARGS 被视为 check() 宏的第一个参数有关,并且以某种方式将空参数归为编译器的第二个参数。 (在我试过的所有编译器上,如果缺少第二个参数,编译器将产生错误)。


您需要一个间接级别以允许您的宏 TEST_ARGS 在传递给 check() 之前展开。

例如:

#define check2(...) check(__VA_ARGS__)

然后,使用check2(TEST_ARGS)


对于 MSVC,我必须做一些更复杂的事情:

#define V_(...) __VA_ARGS__
#define I_(M,...) V_(M(__VA_ARGS__))
#define check2(...) I_(check, __VA_ARGS__)

在顶级(非宏替换)输入中,宏调用参数列表在参数被宏扩展之前立即被解析。 (这一定是这种情况,因为与 ### 宏运算符一起使用的宏参数没有展开,直到检查替换主体才知道。)

然而,替换体中的参数在替换体被替换之前被相应的参数替换(如果参数没有与 ### 一起使用,这些参数将被宏扩展)扫描宏。

所以你可以通过增加一层间接来达到你想要的效果。但是,您可能希望使用可变参数宏,以防调用程序明确输入逗号:

#define CHECK(...) CHECK_(__VA_ARGS__)
#define CHECK_(reg, n) ((reg >> n) & 1U)

#define TEST_ARGS 10, 1
CHECK(TEST_ARGS)

测试:

$ $ gcc -x c -E - <<<'#define CHECK(...) CHECK_(__VA_ARGS__)
> #define CHECK_(reg, n) ((reg >> n) & 1U)
> 
> #define TEST_ARGS 10, 1
> CHECK(TEST_ARGS)'
# 1 "<stdin>"
# 1 "<built-in>"
# 1 "<command-line>"
# 31 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 32 "<command-line>" 2
# 1 "<stdin>"




((10 >> 1) & 1U)