将使用预处理器指令来定义美元符号表示的内容会导致任何冲突

Will using a preprocessor directive to define what a dollar sign represents cause any conflicts?

本文关键字:冲突 任何 表示 符号 预处理 处理器 指令 美元 定义      更新时间:2023-10-16

我可以在C++中使用以下方法吗?

#define $ cout
int main(){
    $<<"Hello World!n";
    return 0;
}

我想知道它是否会引起任何冲突。

它不是绝对合法的,但允许你的实现接受它。

考虑:

[C++11: 2.5/1]: 转换为令牌 (2.7) 的每个预处理令牌应具有关键字、标识符、文本、运算符或标点符号的词法形式。

在这里,你的$显然不是关键字、运算符或标点符号(因为这些在标准中列举),而且它看起来不像文字,所以它只能是一个标识符;现在,标识符必须只包含字母数字和下划线,数字不能是前导的(基于[C++11: 2.11]下表示的语法)。

但是,该标准也允许实现接受其他字符,因此您想要执行的操作可能有效,但它将不可移植。

这是实现定义的行为。 $不包含在标识符的语法中,C++中的标识符名称规则是:

  1. 它不能以数字开头
  2. 可由字母、数字、下划线、通用字符名和实现定义的字符组成
  3. 不能是关键字。

但它确实允许许多编译器支持作为扩展的实现定义的字符,包括 gcc 和 Visual Studio。

实际语法包含在C++标准部分2.11识别草案中:

identifier:
  identifier-nondigit            <- Can only start with a non-digit
  identifier identifier-nondigit <- Next two rules allows for subsequent 
  identifier digit               <-  characters to be those outlined in 2 above
identifier-nondigit:
  nondigit                       <- a-z, A-Z and _ 
  universal-character-name
  other implementation-defined characters
[...]

我们可以看到这适用于第 16 节预处理指令中的define。我们可以从语法中看到,它必须是一个标识符

# define identifier 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
         ^^^^^^^^^^

一些编译器允许在标识符中使用$,这是一个有趣的情况。例如,至少MS VC++ 2010允许在标识符中使用$

因此,例如,如果您定义了

char $ = '$';

然后写

#define $ std::cout
//...
$ << $;

然后,您将在控制台输出数字 1 或某个整数中看到的不是符号 $:)