使用父宏的右括号的C预处理程序 [英] C preprocessor using the closing bracket of a parent macro
问题描述
我有这个有效的代码:
#include <stdio.h>
#define A(x) x B
#define B(x) C(x,
#define C(x,y) y x)
int main( void ) {
printf( A("1") ("2") "3" );
}
它打印132
(A
宏的要点是将括号中遵循其参数的内容与之后的所有内容交换,直到另一个结束括号为止)
It prints 132
(the point of the A
macro is to swap the thing which follows its parameters in brackets with everything after that until another closing bracket)
但是如果我在另一个宏中使用它:
But if I use that within another macro:
#define Z(x) x
printf( Z( A("1") ("2") "3" ) );
我收到编译错误类似函数的宏终止".
I get the compile error "Unterminated function-like macro invocation".
我意识到发生这种情况是因为编译器试图独立处理Z
的参数,但是我需要使用其右括号作为标记.有没有一种方法可以使我在宏中完成此工作?更改调用语法并不是真正的选择.
I realise that this happens because the compiler is trying to process the arguments of Z
independently, but I need to use its closing bracket as a marker. Is there a way I can make this work within macros? Changing the calling syntax isn't really an option.
p.s.在我收到任何谈论这将要做什么的可怕反应之前,请放心:这不是真正的代码.制作一个使用define
在C语言中模拟新语言的玩具程序时出现了一个问题.
p.s. Before I get any responses talking about what an awful thing this is to do, rest assured: this is not for real code. It is a problem which came up while making a toy program which uses define
to simulate a new language inside C.
推荐答案
最简单的方法是稍微改变一下测试用例.
The easiest way to see what's going on is to change the test case a little.
#define A(x) x B
#define B(x) C(x,
#define C(x,y) y x] /* note close square bracket instead of close paren */
Y(A(1)(2)3)
预处理为Y(1 3 2]
.这是因为扩展的中间阶段看起来像
preprocesses to Y(1 3 2]
. This is because an intermediate stage of expansion looked like
Y(1 C(2,3)
这时,C
吃了似乎属于原始文本Y
的近亲 ,并将其替换为右括号.
at which point C
ate the close paren that appeared to belong to Y
in the original text and replaced it with a close bracket.
现在,如果A(1)(2)3
在宏参数中会发生什么变化?
Now, what happens differently if A(1)(2)3
is inside a macro argument?
#define Z(x) x
Z(A(1)(2)3)
由于参数预扫描,扩展的类似中间阶段是 not
Because of argument prescan, the analogous intermediate stage of expansion is not
Z(1 C(2,3)
但是
1 C(2,3
带有Z
的
被隐藏在一个隐藏的待扩展"堆栈中.实际上,预处理器是 enforcecing 的文本外观,即最后的封闭括号属于Z
,并且不允许C
借用它.
with Z
squirrelled away on a hidden "pending expansions" stack. The preprocessor is, in effect, enforcing the textual appearance that that final close paren belongs to Z
, and C
is not allowed to borrow it.
我能想到的达成目标的最小侵入性方法是
The least-invasive way I can think of to achieve your original goal is
#define _A(x) x B
#define B(x) C(x,
#define C(x,y) y x)
#define Z(x) ZZ((_##x))
#define ZZ(x) ZZZ x
#define ZZZ(x) [x]
Z(A(1)(2)3)
预处理到[1 3 2]
.我们使用令牌粘贴运算符来防止预扫描Z
的参数,因此我们可以添加一个临时的额外括号集,以供C
使用. ZZ
和ZZZ
然后再次将它们剥离.要注意的是,如果不将x
粘贴到某物上,将是一个错误,因此我们必须在A
的定义中添加一个前导下划线,如果将A
定义为A
,则会出现错误. Z
的参数的第一个标记永远不是可以在下划线后标记粘贴的东西.
preprocesses to [1 3 2]
. We use the token paste operator to prevent Z
's argument from being prescanned, so we can add a temporary extra set of parentheses for use by C
. ZZ
and ZZZ
then strip them off again. The catch is that it's an error if you don't paste x
with something, so we have to add a leading underscore to the definition of A
, and it will be an error if the first token of Z
's argument is ever not something that can be token-pasted after an underscore.
您可能要考虑使用 M4 ,而不是尝试将其引入C预处理器中
You might want to consider using M4 instead of trying to shoehorn this into the C preprocessor.
这篇关于使用父宏的右括号的C预处理程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!