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)
所以我有这个 '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)