我有一个 C 宏,它将位连接在一起以便解析为其他宏。我将使用一个名为
MULT
的毫无意义的宏来演示,它可以将两个数字相乘。只要我将实际的文字整数传递给它的第一个参数,它就可以工作。但是传入数学表达式会触发错误。
例如:
#define MULT_2(X) X+X
#define MULT_3(X) X+X+X
#define MULT_4(X) X+X+X+X
#define EXPAND_(A) A
#define MULT__(N, X) EXPAND_(MULT_ ## N)(X)
#define MULT_(N, X) MULT__(N, X)
#define MULT(N, X) MULT_(EXPAND_(N), X)
int main() {
int num;
// This works:
num = MULT(4, 1);
printf("num: %d\n", num);
// This does not:
num = MULT(2+2, 1);
printf("num: %d\n", num);
return 0;
}
(说实话,我不完全理解为什么让这个宏仅使用文字整数需要三个额外的宏,
MULT_
,MULT__
和EXPAND_
。但无论如何......)
有没有办法重写这个,以便将像
2+2
或 1 * 4
或 1 << 2
这样的表达式传递给它的第一个参数实际上会起作用?
我对这个答案很好奇,主要是为了拓宽我对 C 及其预处理器的了解。但我也希望在一个用 C89 编写的项目中使用它,这意味着没有可变参数宏,所以如果有一个解决方案可以避免使用这些宏,我很乐意看到它!
无论出于何种意图和目的,这都是不可能的。 C 宏字符串连接 (##) 不会计算表达式,它仅将它们转换为字符串文字。
这就是您创建的宏在尝试连接数学表达式时扩展到的内容:
#define MULT_2(X) X + X
#define MULT_3(X) X + X + X
#define MULT_4(X) X + X + X + X
#define EXPAND_(A) A
#define MULT__(N, X) EXPAND_(MULT_##N)(X)
#define MULT_(N, X) MULT__(N, X)
#define MULT(N, X) MULT_(EXPAND_(N), X)
// MULT(2+2, 1)
MULT_2 + 2(1)
这显然不是想要的效果。