我偶然发现了一些C++代码如下:
int $T$S;
首先,我认为它是某种PHP代码或错误地粘贴在那里的东西,但它编译和运行良好(在MSVC 2008上)。在C++中,哪些字符对变量有效?还有其他奇怪的字符可以使用?
wlzqhblo1#
根据该标准,唯一法律的的字符是字母数字和下划线。该标准确实要求Unicode认为字母的任何东西都是可以接受的(但只能作为单个代码点字符)。在实践中,实现提供了扩展(即有些确实接受$)和限制(大多数不接受所有必需的Unicode字符)。如果希望代码可移植,请将符号限制为26个无重音字母、大写或小写、10位数字和'_'。
mkh04yzy2#
它是一些编译器的扩展,不在C标准中
只有Microsoft C++标识符的前2048个字符是有效的。用户定义类型的名称由编译器“修饰”以保留类型信息。结果名称(包括类型信息)不能超过2048个字符。(有关详细信息,请参阅修饰名称。)影响修饰标识符长度的因素有:
// dollar_sign_identifier.cpp struct $Y1$ { void $Test$() {} }; int main() { $Y1$ $x$; $x$.$Test$(); }
https://web.archive.org/web/20100216114436/http://msdn.microsoft.com/en-us/library/565w213d.aspx最新版本:https://learn.microsoft.com/en-us/cpp/cpp/identifiers-cpp?redirectedfrom=MSDN&view=vs-2019
在GNU C中,通常可以在标识符名称中使用美元符号。这是因为许多传统的C实现允许这样的标识符。但是,在少数目标计算机上不支持标识符中的美元符号,这通常是因为目标汇编程序不允许使用美元符号。http://gcc.gnu.org/onlinedocs/gcc/Dollar-Signs.html#Dollar-Signs
ar7v8xwq3#
据我所知,根据标准,只有字母(大写和小写)、数字(0到9)和**_**才是有效的变量名(注意:变量名不应该以数字开头)。所有其他字符都应该是编译器扩展名。
0
9
_
zzzyeukh4#
这不是一个好的做法。通常,您应该只在标识符中使用字母数字字符和下划线([a-z][A-Z][0-9]_)。
[a-z][A-Z][0-9]_
与其他语言(bash,perl)不同,C不使用$来表示变量的用法。因此,它在技术上是有效的。在C中,它很可能福尔斯C11,6.4.2。这意味着它似乎得到了现代编译器的支持。至于你的C++问题,让我们测试一下!
$
int main(void) { int $ = 0; return $; }
在GCC/G++/Clang/Clang++上,这确实可以编译,并且运行得很好。
编译器获取源代码,将其放入令牌流中,将其放入抽象语法树(AST)中,然后使用它来生成代码(例如汇编/LLVM IR)。你的问题实际上只围绕第一部分(例如)。lexing)。C/C++的语法(也就是词法分析器的实现)并不把$当作特殊的,不像逗号、句点、瘦箭头等等。因此,你可能会从下面的c代码中得到一个像这样的lexer输出:
int i_love_$ = 0;
在lexer之后,这变成了一个令牌流,如下所示:
["int", "i_love_$", "=", "0"]
如果你把这个代码带到哪里:
int i_love_$,_and_.s = 0;
lexer将输出一个令牌流,如下所示:
["int", "i_love_$", ",", "_and_", ".", "s", "=", "0"]
正如你所看到的,因为C/C++不把像$这样的字符当作特殊字符,所以它的处理方式与其他字符(如句点)不同。
4条答案
按热度按时间wlzqhblo1#
根据该标准,唯一法律的的字符是字母数字和下划线。该标准确实要求Unicode认为字母的任何东西都是可以接受的(但只能作为单个代码点字符)。在实践中,实现提供了扩展(即有些确实接受$)和限制(大多数不接受所有必需的Unicode字符)。如果希望代码可移植,请将符号限制为26个无重音字母、大写或小写、10位数字和'_'。
mkh04yzy2#
它是一些编译器的扩展,不在C标准中
MSVC:
微软专用
只有Microsoft C++标识符的前2048个字符是有效的。用户定义类型的名称由编译器“修饰”以保留类型信息。结果名称(包括类型信息)不能超过2048个字符。(有关详细信息,请参阅修饰名称。)影响修饰标识符长度的因素有:
美元符号在Visual C++中也是有效的标识符。
https://web.archive.org/web/20100216114436/http://msdn.microsoft.com/en-us/library/565w213d.aspx
最新版本:https://learn.microsoft.com/en-us/cpp/cpp/identifiers-cpp?redirectedfrom=MSDN&view=vs-2019
GCC:
6.42标识符名称中的美元符号
在GNU C中,通常可以在标识符名称中使用美元符号。这是因为许多传统的C实现允许这样的标识符。但是,在少数目标计算机上不支持标识符中的美元符号,这通常是因为目标汇编程序不允许使用美元符号。
http://gcc.gnu.org/onlinedocs/gcc/Dollar-Signs.html#Dollar-Signs
ar7v8xwq3#
据我所知,根据标准,只有字母(大写和小写)、数字(
0
到9
)和**_
**才是有效的变量名(注意:变量名不应该以数字开头)。所有其他字符都应该是编译器扩展名。
zzzyeukh4#
这不是一个好的做法。通常,您应该只在标识符中使用字母数字字符和下划线(
[a-z][A-Z][0-9]_
)。表面水平
与其他语言(bash,perl)不同,C不使用
$
来表示变量的用法。因此,它在技术上是有效的。在C中,它很可能福尔斯C11,6.4.2。这意味着它似乎得到了现代编译器的支持。至于你的C++问题,让我们测试一下!
在GCC/G++/Clang/Clang++上,这确实可以编译,并且运行得很好。
更深层次
编译器获取源代码,将其放入令牌流中,将其放入抽象语法树(AST)中,然后使用它来生成代码(例如汇编/LLVM IR)。你的问题实际上只围绕第一部分(例如)。lexing)。
C/C++的语法(也就是词法分析器的实现)并不把
$
当作特殊的,不像逗号、句点、瘦箭头等等。因此,你可能会从下面的c代码中得到一个像这样的lexer输出:在lexer之后,这变成了一个令牌流,如下所示:
如果你把这个代码带到哪里:
lexer将输出一个令牌流,如下所示:
正如你所看到的,因为C/C++不把像$这样的字符当作特殊字符,所以它的处理方式与其他字符(如句点)不同。