为啥标识符可以在 C 中包含“$”? [复制]

Posted

技术标签:

【中文标题】为啥标识符可以在 C 中包含“$”? [复制]【英文标题】:Why can identifiers contain '$' in C? [duplicate]为什么标识符可以在 C 中包含“$”? [复制] 【发布时间】:2021-07-11 07:18:08 【问题描述】:

最近看到这样的代码:

int $ = 123;

那么为什么 '$' 可以在 C 中的标识符中呢?

在 C++ 中也一样吗?

【问题讨论】:

它是许多编译器默认实现的 C 语言的扩展。如果您不想要它,则需要明确禁用它。对于 gcc 和 clang,它将是一个恰当命名的 -fno-dollars-in-identifiers 命令行选项。 $ symbol in C variable names, What are the '@' and '$' for in C/C++? 切题:VMS 操作系统非常喜欢到处都有美元符号——将引导设备称为 SYS$SYSDEVICE 之类的东西。我怀疑例如gcc 养成了允许 $ 以适应该环境的习惯。 @Jens:如果 C 实现允许在标识符中使用 $,这符合 C 标准,并且当程序在允许它的 C 实现中的标识符中使用 $ 时,也符合C标准。 【参考方案1】:

这不是一个好习惯。通常,您只能在标识符中使用字母数字字符和下划线 ([a-z][A-Z][0-9]_)。

表面水平

与其他语言(bash、perl)不同,C 不使用$ 来表示变量的使用。因此,它在技术上是有效的。从 C++ 17 开始,这是符合标准的,请参阅草案 n4659。在 C 中,它很可能属于 C11, 6.4.2。这意味着现代编译器似乎确实支持它。

至于你的 C++ 问题,让我们测试一下!

int main(void) 
    int $ = 0;
    return $;

在 GCC/G++/Clang/Clang++ 上,这确实可以编译,并且运行良好。

更深层次

编译器获取源代码,将其转换为令牌流,将其放入抽象语法树 (AST),然后使用它生成代码(例如汇编/LLVM IR)。您的问题实际上只围绕第一部分(例如词法分析)。

C/C++ 的语法(因此词法分析器实现)不会将 $ 视为特殊的,不像逗号、句号、细箭头等...因此,您可能会从词法分析器中获得这样的输出下面的c代码:

int i_love_$ = 0;

在词法分析器之后,这变成了这样的令牌流:

["int", "i_love_$", "=", "0"]

如果您在哪里获取此代码:

int i_love_$,_and_.s = 0;

词法分析器会输出一个令牌流,如:

["int", "i_love_$", ",", "_and_", ".", "s", "=", "0"]

如您所见,由于 C/C++ 不会将 $ 之类的字符视为特殊字符,因此它的处理方式与句点等其他字符不同。

【讨论】:

参见 C11, 6.4.2。它可能属于“其他实现定义的字符”【参考方案2】:

2018 C 标准在 6.4.2 1 中规定,标识符由 nondigit 字符组成,后跟零个或多个 nondigitdigit 字符,其中 nondigit 字符是:

_azAZ 的字符之一, 一个通用字符名,即\u后跟四个十六进制数字或\U后跟八个十六进制数字,超出特定范围1 , 或 实现定义的字符。

数字字符是09

以 GCC 为例,它的文档是 these additional characters are defined in its preprocessor section,而那个部分是 GCC accepts $ and the characters that correspond to the universal character names。2 因此,允许 $ 是编译器实现者的选择。

2017 C++ 标准草案 n4659 在第 5.10 条 [lex.name] 中具有相同的规则,但它进一步限制了通用字符名称。

脚注

1 这些\u\U 形式允许您将任何字符写为十六进制代码。排除的范围是 C 的基本字符集中的范围以及为控制字符和特殊用途保留的代码。

2 “通用字符名称”是\u\U 形式。与它们相对应的字符就是那些形式所代表的字符。例如,π 是通用字符,\u03c0 是它的通用字符名称。

【讨论】:

以上是关于为啥标识符可以在 C 中包含“$”? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

在 URI 中包含斜杠字符“/”的标识符

如何处理 Template Toolkit 中包含非法标识符字符的哈希键?

如何连接相对路径或生成嵌套文件夹中包含的唯一标识符 svg?

为啥 Ruby 的 bcrypt 库在哈希中包含明文中的盐? [复制]

为啥 $ 符号不能用作标识符的一部分? [复制]

在http请求中包含了哪些信息