可以(或可以)通过将名称括在括号中来抑制C中的宏替换

时间:2021-04-19 20:32:56

I seem to recall that one could suppress replacement (expansion) of a macro in C by placing the macro name in brackets, e.g. (free)(p) would call the function free whether or not a macro free were defined. I see no mention of this in the C99 standard (it is there, see answer), and I observe that MSVS 2013 does not implement it either. Added in light of answer: It does, just as the standard requires, i.e. only for function-like macros, whose expansion is triggered by a following ‘( and thus inhibited by the intervening ‘)’.

我似乎记得,可以通过将宏名称放在括号中来抑制C中宏的替换(扩展),例如(免费)(p)无论是否定义了宏,都会调用该函数。我在C99标准中没有提到这一点(它在那里,见答案),我观察到MSVS 2013也没有实现它。根据答案添加:它正如标准所要求的那样,即仅适用于类似函数的宏,其扩展由后续'('因此被介入''抑制)触发。

Am I dreaming, or was there such a possibility, and if so, what was the rationale for withdrawing it? Or was present only in certain dialects?

我是在做梦,还是有这样的可能性,如果有的话,撤回它的理由是什么?或只出现在某些方言?

1 个解决方案

#1


8  

A function-like macro FOO

一个类似函数的宏FOO

#define FOO(x) ...

is only expanded when the token FOO appears followed by a ( token. Thus, to prevent the expansion of FOO, (FOO) can be used. Just as you said. This however only applies to function-like macros.

仅当令牌FOO出现后跟(令牌)时才会展开。因此,为了防止FOO的扩展,可以使用(FOO)。就像你说的那样。但是这仅适用于类似函数的宏。

This is specified in ISO 9899:2011 §6.10.3 ¶10, which reads:

这在ISO 9899:2011§6.10.3¶10中规定,其内容如下:

10 A preprocessing directive of the form

10表单的预处理指令

# define identifier lparen identifier-listopt ) replacement-list new-line
# define identifier lparen ... ) replacement-list new-line
# define identifier lparen identifier-list , ... ) replacement-list new-line

#define identifier lparen identifier-listopt)replacement-list new-line #define identifier lparen ...)replacement-list new-line #define identifier lparen identifier-list,...)replacement-list new-line

defines a function-like macro with parameters, whose use is similar syntactically to a function call. The parameters are specified by the optional list of identifiers, whose scope extends from their declaration in the identifier list until the new-line character that terminates the #define preprocessing directive. Each subsequent instance of the function-like macro name followed by a ( as the next preprocessing token introduces the sequence of preprocessing tokens that is replaced by the replacement list in the definition (an invocation of the macro). The replaced sequence of preprocessing tokens is terminated by the matching ) preprocessing token, skipping intervening matched pairs of left and right parenthesis preprocessing tokens. Within the sequence of preprocessing tokens making up an invocation of a function-like macro, new-line is considered a normal white-space character.

定义一个带有参数的类函数宏,其用法在语法上与函数调用类似。参数由可选的标识符列表指定,其范围从它们在标识符列表中的声明扩展到终止#define预处理指令的换行符。类似函数的宏名称的每个后续实例后跟一个(作为下一个预处理标记引入了预处理标记序列,该标记由定义中的替换列表替换(宏的调用)。预处理标记的替换序列是由匹配的预处理令牌终止,跳过中间匹配的左右括号预处理令牌对。在组成函数式宏的调用的预处理令牌序列中,换行被认为是正常的空白字符。

#1


8  

A function-like macro FOO

一个类似函数的宏FOO

#define FOO(x) ...

is only expanded when the token FOO appears followed by a ( token. Thus, to prevent the expansion of FOO, (FOO) can be used. Just as you said. This however only applies to function-like macros.

仅当令牌FOO出现后跟(令牌)时才会展开。因此,为了防止FOO的扩展,可以使用(FOO)。就像你说的那样。但是这仅适用于类似函数的宏。

This is specified in ISO 9899:2011 §6.10.3 ¶10, which reads:

这在ISO 9899:2011§6.10.3¶10中规定,其内容如下:

10 A preprocessing directive of the form

10表单的预处理指令

# define identifier lparen identifier-listopt ) replacement-list new-line
# define identifier lparen ... ) replacement-list new-line
# define identifier lparen identifier-list , ... ) replacement-list new-line

#define identifier lparen identifier-listopt)replacement-list new-line #define identifier lparen ...)replacement-list new-line #define identifier lparen identifier-list,...)replacement-list new-line

defines a function-like macro with parameters, whose use is similar syntactically to a function call. The parameters are specified by the optional list of identifiers, whose scope extends from their declaration in the identifier list until the new-line character that terminates the #define preprocessing directive. Each subsequent instance of the function-like macro name followed by a ( as the next preprocessing token introduces the sequence of preprocessing tokens that is replaced by the replacement list in the definition (an invocation of the macro). The replaced sequence of preprocessing tokens is terminated by the matching ) preprocessing token, skipping intervening matched pairs of left and right parenthesis preprocessing tokens. Within the sequence of preprocessing tokens making up an invocation of a function-like macro, new-line is considered a normal white-space character.

定义一个带有参数的类函数宏,其用法在语法上与函数调用类似。参数由可选的标识符列表指定,其范围从它们在标识符列表中的声明扩展到终止#define预处理指令的换行符。类似函数的宏名称的每个后续实例后跟一个(作为下一个预处理标记引入了预处理标记序列,该标记由定义中的替换列表替换(宏的调用)。预处理标记的替换序列是由匹配的预处理令牌终止,跳过中间匹配的左右括号预处理令牌对。在组成函数式宏的调用的预处理令牌序列中,换行被认为是正常的空白字符。