为什么我需要宏的双层间接? [英] Why do I need double layer of indirection for macros?

查看:20
本文介绍了为什么我需要宏的双层间接?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在:C++ FAQ - 其他技术问题 - [39.6] 需要将两个标记粘贴在一起的宏应该怎么做?

谁能解释一下为什么?我读到的只是相信我,但我不能仅仅因为有人这么说就相信某事.

Could someone explain to me why? All I read is trust me, but I simply can't just trust on something because someone said so.

我尝试了该方法,但找不到任何出现的错误:

I tried the approach and I can't find any bugs appearing:

#define mymacro(a) int a ## __LINE__
mymacro(prefix) = 5;
mymacro(__LINE__) = 5;
int test = prefix__LINE__*__LINE____LINE__; // fine

那么为什么我需要这样做(引自网页):

So why do I need to do it like this instead (quote from the webpage):

但是,当您使用## 时,您需要双层间接.基本上,您需要为令牌粘贴"创建一个特殊的宏,例如如:

However you need a double layer of indirection when you use ##. Basically you need to create a special macro for "token pasting" such as:

 #define NAME2(a,b)         NAME2_HIDDEN(a,b)
 #define NAME2_HIDDEN(a,b)  a ## b 

相信我——你真的需要这样做这!(请没有人给我写信说它有时没有第二层间接.尝试将符号与__ LINE__ 看看会发生什么.)

Trust me on this — you really need to do this! (And please nobody write me saying it sometimes works without the second layer of indirection. Try concatenating a symbol with __ LINE__ and see what happens then.)

有人能解释一下为什么他在下面声明之前使用 NAME2_HIDDEN 吗?在我使用它之前定义 NAME2_HIDDEN 宏似乎更合乎逻辑.这是什么诡计吗?

Could someone also explain why he uses NAME2_HIDDEN before it's declared below? It seems more logical to define NAME2_HIDDEN macro before I use it. Is it some sort of trick here?

推荐答案

C规范的相关部分:

6.10.3.1 参数替换

6.10.3.1 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.

决定是否要双重间接寻址的关键部分是第二句和其中的异常——如果参数涉及到### 操作(例如 mymacroNAME2_HIDDEN 中的参数),则在执行 # 之前不会扩展参数中的任何其他宏或 ##.另一方面,如果宏体中没有 ### 立即(与 NAME2 一样),那么在参数已扩展.

The key part that determines whether you want the double indirection or not is the second sentence and the exception in it -- if the parameter is involved in a # or ## operation (such as the params in mymacro and NAME2_HIDDEN), then any other macros in the argument are NOT expanded prior to doing the # or ##. If, on the other hand, there's no # or ## IMMEDIATELY in the macro body (as with NAME2), then other macros in the parameters ARE expanded.

所以这取决于你想要什么 - 有时你希望首先扩展所有宏,然后执行 ### (在这种情况下,你想要双层间接),有时你不希望先扩展宏(在这种情况下你不能有双层宏,你需要直接做.)

So it comes down to what you want -- sometimes you want all macros expanded FIRST, and then do the # or ## (in which case you want the double layer indirection) and sometime you DO NOT want the macros expanded first (in which case you CAN'T HAVE double layer macros, you need to do it directly.)

这篇关于为什么我需要宏的双层间接?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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