C预处理器宏定义多个参数

3

我有一个名为“check”的宏,接受两个参数:

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

我有以下这个参数列表:

#define TEST_ARGS 10, 1

代码:

check(TEST_ARGS);

扩展预期:

((10 >> 1) & 1U)

实际扩展:

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

我该如何为“check”宏定义多个参数以获取预期结果?谢谢。
3个回答

2
在顶层(未替换的宏)输入中,宏调用参数列表会被立即解析,而不是在宏扩展之后。这必须是这样的,因为使用 # 和 ## 宏运算符的宏参数不会被扩展,这一点在检查替换主体之前是无法知道的。
然而,在替换主体中的参数将被相应的参数替换(如果该参数未与 # 或 ## 一起使用,则已扩展该参数),然后再扫描替换主体中的宏。
因此,您可以通过添加一个间接层来实现所需的效果。但是,您可能希望使用可变参数宏,以防调用者放入显式逗号。
#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)

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__)

这很有帮助。我很蠢,遇到了类似的问题,即10,1被视为单个标记而不是两个参数。 - mint branch conditioner

0

预处理器执行文本替换(实际上是替换标记)。因此,如果

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

那么

check(TEST_ARGS);

被预处理为:

check(10, 1,);  

第一个参数是完整的令牌10,1,第二个参数为空


能否将它变成 "check(10, 1);"? - malidu
@malidu 为什么? - 0___________

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接