【问题标题】:Does C++11 allow dollar signs in identifiers?C++11 是否允许在标识符中使用美元符号?
【发布时间】:2014-10-10 14:26:48
【问题描述】:

Are dollar-signs allowed in identifiers in C++03? 涵盖了标识符中的美元符号在 C++03 中是不允许的。 GCC 以C extension 的形式提供它,并在 C++03 模式下正确给出诊断。但是,在 C++11 中,int $ = 0 将在没有警告的情况下编译。

answer 原因可能允许$,因为实现定义的标识符不需要诊断:

这里的答案是“也许”:根据§2.11,标识符 可能由 digitsidentifier-nondigits 组成,从一个开始 后者。 identifier-nondigits 是通常的a-zA-Z 和 下划线,此外,自 C++11 起,它们还包括 通用字符名称(例如\uBEAF\UC0FFEE32)、和其他实现定义的字符。所以它是实现定义的 如果允许在标识符中使用$。 VC10 及更高版本支持, 也许更早的版本也是如此。它甚至支持标识符,例如 こんばんわ

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

这种语言也出现在 C++03 标准中,所以我认为这不是一个非常有说服力的论点。

§2.10/2

另外,有些标识符是保留给 C++ 使用的 实现和标准库(17.6.4.3.2),不得 以其他方式使用;不需要诊断。

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

【问题讨论】:

  • Clang 对此发出警告。
  • @Shafik 令人困惑的是,answer 链接到旧的 gcc 文档,该文档明确指出 C++ 禁止在标识符中使用 $。他们将其移至preprocessor options,唯一的描述为Accept ‘$’ in identifiers.
  • 历史上,DEC 在其所有系统服务和库函数名称中使用 $,而在其所有内部函数中使用 $$。所有的 DEC 编译器要么扩展允许 $ 符号名称或 pragma 用于映射(与 ADA 一样)。
  • 使用 GCC 4.9.2,我发现 $ 似乎是允许的,除了作为第一个字符。这真让我吃惊。我最近在github.com/rollbear/basicp 的搞笑 BASIC 仿真器中第一次看到这个。我查看了源代码以了解究竟如何支持 $ 符号。令人惊讶的是:原生!但是,显然,应该避免使用 $,因为它似乎不是标准的或可移植的。 (另一方面,GCC 不喜欢英镑。嘘!)

标签: c++ c++11 language-lawyer identifier


【解决方案1】:

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

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

实现定义的字符是允许的,并且许多编译器支持作为扩展名,包括gccclangVisual Studiocomment 中明显提到的DEC C++ compilers

语法在draft C++ standard 部分2.11 Indentifier 中介绍,我添加了以<- 开头的附加注释:

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;
    ^

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • “不可移植”和“不允许”(格式不正确)都是坏事,但不一样。所以这不是问题的直接答案。
    • 我很清楚这一点。我在这里使用“不可移植”作为“实现定义的行为”的同义词。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-20
    • 2012-09-30
    • 2013-05-10
    • 1970-01-01
    • 2011-02-18
    相关资源
    最近更新 更多