为啥标识符可以在 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 字符组成,后跟零个或多个 nondigit 或 digit 字符,其中 nondigit 字符是:
_
、a
到 z
或 A
到 Z
的字符之一,
一个通用字符名,即\u
后跟四个十六进制数字或\U
后跟八个十六进制数字,超出特定范围1 , 或
实现定义的字符。
数字字符是0
到9
。
以 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 中包含“$”? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
如何处理 Template Toolkit 中包含非法标识符字符的哈希键?
如何连接相对路径或生成嵌套文件夹中包含的唯一标识符 svg?