C++11允许在标识符中使用美元符号吗?

24

Are dollar-signs allowed in identifiers in C++03? 涵盖了在C++03中不允许在标识符中使用美元符号。GCC将其作为C扩展提供,并在C++03模式下适当地给出诊断。但是,在C++11中,int $ = 0将编译而不会发出警告。

这个答案认为可能允许使用$,因为实现定义的标识符不需要进行诊断:

这里的答案是"可能":根据§2.11,标识符可以由数字和标识符非数字组成,以后者之一开头。标识符非数字通常是 a-zA-Z 和下划线,自C++11以来还包括 通用字符名(例如 \uBEAF\UC0FFEE32),以及其他实现定义字符。因此,在标识符中使用$是否允许是实现定义的。VC10及以上版本支持该功能,也可能支持更早版本。它甚至支持像こんばんわ这样的标识符。

但是:我不会使用它们。使标识符尽可能易读和可移植。 $是实现定义的,因此不可移植。

这个语言也出现在C++03标准中,因此我认为这不是一个非常令人信服的论点。

§2.10/2

此外,一些标识符为C++实现和标准库(17.6.4.3.2)所保留,不得以其他方式使用;不需要发出诊断。

标准中的哪些变化允许将$用作标识符名称?


2
Clang 对此发出警告。 - T.C.
@Shafik 令人困惑的是,这个答案链接到旧的gcc文档,明确表示C ++禁止在标识符中使用$。他们将其移动到预处理器选项,唯一的描述是接受标识符中的‘$’ - user3920237
从历史上看,DEC在其所有系统服务和库函数名称中使用$符号,并在其所有内部函数中使用$$符号。所有DEC编译器都允许使用$符号名称的扩展或用于映射的编译指示(如ADA)。 - user3344003
使用 GCC 4.9.2 版本,我发现 $ 符号似乎除了第一个字符外都是允许的。这真的让我吃惊。我最近在 https://github.com/rollbear/basicp 上看到它被用于有趣的 BASIC 模拟器中。我查看了源代码以找出 $ 符号是如何被支持的。令人惊讶的是:原生支持!但是,显然应该避免使用 $,因为它似乎不是标准或可移植的。(另一方面,GCC 不喜欢 £。Boo!) - Rhubbarb
2个回答

22
这是实现定义的行为,标识符语法中不包括$。在C++11中,标识符名称的规则如下:
  1. 不能以数字开头
  2. 可以由字母、数字、下划线、通用字符名称和实现定义的字符组成
  3. 不能是关键字

实现定义的字符被允许,并且许多编译器支持作为扩展,包括gccclangVisual Studio,并且如评论中所述,显然DEC C++编译器也支持。

该语法在草案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
[...]
如果我们使用-pedantic-errors标志来编译此代码,使用clang将无法编译:
int $ = 0

并生成以下错误:

error: '$' in identifier [-Werror,-Wdollar-in-identifier-extension]
int $ = 0;
    ^

3

我不这么认为。美元符号在ASCII 0x24中,它不在标准附录E.1(charname.allowed)定义的任何范围内。由于它既不是数字也不是非数字,因此它必须是一个实现定义的字符。因此,我同意这不是可移植的C++11。还要注意,标识符不得以通用字符开头,虽然它允许标识符以实现允许的字符开头。


1
“不可移植”和“不允许”(格式不正确)都是不好的事情,但并不相同。因此,这不是对问题的直接回答。 - MSalters
1
我非常清楚这一点。在这里,我使用“不可移植”作为“实现定义行为”的同义词。 - dom0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接