如何与C preprocessor两次连接起来,扩大宏如在QUOT;阿根廷## _ ## MACRO"? [英] How to concatenate twice with the C preprocessor and expand a macro as in "arg ## _ ## MACRO"?

查看:154
本文介绍了如何与C preprocessor两次连接起来,扩大宏如在QUOT;阿根廷## _ ## MACRO"?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图写一个程序,其中的某些功能的名称是依赖于一定的宏观变量,像这样的宏值:

 #定义变量3
的#define NAME(有趣)有趣的## _ ##变INT NAME(some_function)(int类型的);

不幸的是,宏 NAME()变成了成

  INT some_function_VARIABLE(int类型的);

而不是

  INT some_function_3(int类型的);

所以这显然是错误的方式去了解它。幸运的是,不同的可能值的变量数量很小,所以我可以简单地做一个#如果变量==ñ并单独列出所有的情况下,但我不知道是否有是一个聪明的办法做到这一点。


解决方案

  $猫xx.c
#定义变量3
帕斯特的#define(X,Y)×## _ ##ÿ
#定义EVALUATOR(X,Y)帕斯特(X,Y)
的#define NAME(FUN)EVALUATOR(好玩,可变)EXTERN无效NAME(矿)(字符* X);
$ gcc的-E xx.c
#1xx.c
#1<内置>中
#1<命令行>中
#1xx.cEXTERN无效mine_3(字符* X);
$


凯德空肠Roux <一个href=\"http://stackoverflow.com/questions/1489932/c-$p$pprocessor-and-token-concatenation/1489985#comment1342105_1489971\">asked为什么这需要间接两个层次。该轻率的回答是,因为这是标准如何规定它的工作;你会发现你需要用字符串化运营,相当于招了。

C99的标准包括宏替换,并6.10.3.1盖的说法取代第6.10.3。


  一个函数宏的调用的参数已经确定

后,
  参数替换发生。在替换列表中的参数,除非preceded
  由 ## preprocessing令牌或后跟一个 ## preprocessing令牌(见下文),是
  通过相应的参数后更换其中所载所有宏一直
  扩大。之前被取代,每个参数的preprocessing令牌
  完全取代宏,如果他们形成了preprocessing文件的剩余部分;没有其他
  preprocessing令牌是可用的。


在调用 NAME(矿)的说法是我的;它完全扩展到我的;它然后代入替换字符串:

  EVALUATOR(矿,可变)

现在宏观EVALUATOR被发现,并且参数被隔离为我的和变量;后者然后完全膨胀至'3',并代入替换字符串

 帕斯特(矿,3)

的这个操作由其他规则覆盖(6.10.3.3'的##运算符'):


  

如果在一个函数宏的替换列表,参数立即preceded
  或者在一个 ## preprocessing道理,参数由相应的取代
  参数的preprocessing令牌序列; [...]


  
  

对于这两种对象类和函数宏调用,之前替换名单
  复查更多的宏名来代替,一个 ## preprocessing令牌的每个实例
  在替换列表(没有一个参数)将被删除,preceding preprocessing
  令牌的值与以下preprocessing令牌。


所以,更换列表中包含 X 然后按 ## ## 然后按;所以我们有:

 矿山## _ ## 3

和消除 ## 标记,并在两侧收割机我的与串联令牌'_'和'3'的收益率:

  mine_3

这是期望的结果。


如果我们看一下原来的问题,在code的(适合于使用,而不是'some_function'矿')

 #定义变量3
的#define NAME(有趣)有趣的## _ ##变NAME(矿)

要NAME的说法显然是我的,并且完全展开。结果
继6.10.3.3的规则,我们发现:

 矿山## _ ##变

其中,当 ## 运营商被淘汰,映射到:

  mine_VARIABLE

正是因为报道的问题。

I am trying to write a program where the names of some functions are dependent on the value of a certain macro variable with a macro like this:

#define VARIABLE 3
#define NAME(fun) fun ## _ ## VARIABLE

int NAME(some_function)(int a);

Unfortunately, the macro NAME() turns that into

int some_function_VARIABLE(int a);

rather than

int some_function_3(int a);

so this is clearly the wrong way to go about it. Fortunately, the number of different possible values for VARIABLE is small so I can simply do an #if VARIABLE == n and list all the cases separately, but I was wondering if there is a clever way to do it.

解决方案

$ cat xx.c
#define VARIABLE 3
#define PASTER(x,y) x ## _ ## y
#define EVALUATOR(x,y)  PASTER(x,y)
#define NAME(fun) EVALUATOR(fun, VARIABLE)

extern void NAME(mine)(char *x);
$ gcc -E xx.c
# 1 "xx.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "xx.c"





extern void mine_3(char *x);
$


Cade Roux asked why this needs two levels of indirection. The flippant answer is because that's how the standard requires it to work; you tend to find you need the equivalent trick with the stringizing operator too.

Section 6.10.3 of the C99 standard covers 'macro replacement', and 6.10.3.1 covers 'argument substitution'.

After the arguments for the invocation of a function-like macro have been identified, argument substitution takes place. A parameter in the replacement list, unless preceded by a # or ## preprocessing token or followed by a ## preprocessing token (see below), is replaced by the corresponding argument after all macros contained therein have been expanded. Before being substituted, each argument’s preprocessing tokens are completely macro replaced as if they formed the rest of the preprocessing file; no other preprocessing tokens are available.

In the invocation NAME(mine), the argument is 'mine'; it is fully expanded to 'mine'; it is then substituted into the replacement string:

EVALUATOR(mine, VARIABLE)

Now the macro EVALUATOR is discovered, and the arguments are isolated as 'mine' and 'VARIABLE'; the latter is then fully expanded to '3', and substituted into the replacement string:

PASTER(mine, 3)

The operation of this is covered by other rules (6.10.3.3 'The ## operator'):

If, in the replacement list of a function-like macro, a parameter is immediately preceded or followed by a ## preprocessing token, the parameter is replaced by the corresponding argument’s preprocessing token sequence; [...]

For both object-like and function-like macro invocations, before the replacement list is reexamined for more macro names to replace, each instance of a ## preprocessing token in the replacement list (not from an argument) is deleted and the preceding preprocessing token is concatenated with the following preprocessing token.

So, the replacement list contains x followed by ## and also ## followed by y; so we have:

mine ## _ ## 3

and eliminating the ## tokens and concatenating the tokens on either side combines 'mine' with '_' and '3' to yield:

mine_3

This is the desired result.


If we look at the original question, the code was (adapted to use 'mine' instead of 'some_function'):

#define VARIABLE 3
#define NAME(fun) fun ## _ ## VARIABLE

NAME(mine)

The argument to NAME is clearly 'mine' and that is fully expanded.
Following the rules of 6.10.3.3, we find:

mine ## _ ## VARIABLE

which, when the ## operators are eliminated, maps to:

mine_VARIABLE

exactly as reported in the question.

这篇关于如何与C preprocessor两次连接起来,扩大宏如在QUOT;阿根廷## _ ## MACRO&QUOT;?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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