使用父宏的右括号的C预处理程序 [英] C preprocessor using the closing bracket of a parent macro

查看:99
本文介绍了使用父宏的右括号的C预处理程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个有效的代码:

#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使用. ZZZZZ然后再次将它们剥离.要注意的是,如果不将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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆