问题描述
在: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.
决定是否需要双重间接引用的关键部分是第二句和其中的异常——如果参数涉及#
或##
操作(例如 mymacro
和 NAME2_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.)
这篇关于为什么宏需要双层间接?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!