C和C++都支持一组看似等价的转义序列,如b
、t
、n
、"
和其他以反斜杠字符((开头的转义序列。如果后面跟着正常字符,如何处理反斜杠?据我记忆所及,从几个编译器中,转义符
被无声地跳过。在cppreference.com上,我阅读了以下文章
- 转义序列(C(
- 转义序列(C++(
我只在C文章中找到了关于孤立反斜杠的注释
如果反斜杠后面跟有任何未在此处列出的字符,ISO C需要进行诊断:〔…〕
引用表上方的
。我还看了一些在线编译器
C演示
#include <stdio.h>
int main(void) {
// your code goes here
printf("%d", !strcmp("\ x", "\ x"));
printf("%d", !strcmp("\ x", "\ x"));
printf("%d", !strcmp("\ x", "\\ x"));
return 0;
}
C++演示
#include <iostream>
#include <string>
using namespace std;
int main() {
cout << (string("\ x") == "\ x");
cout << (string("\ x") == "\ x");
cout << (string("\ x") == "\\ x");
return 0;
}
两者都将"\ x"
和"\ x"
视为等效的,(某种(通过语法高亮显示进行警告。IOW"\ x"
已转化为CCD_。
我可以假设这是定义的行为吗?
澄清(编辑(
- 我不是在问像
""
这样明显无效的字符串文字 - 我知道孤立反斜杠有点问题
- 我想知道结果,编译器构建的常量,是否是定义的
编辑#2:更加关注生成的常量(和可移植性(。
答案是否定的。这是一个无效的C程序,未指定的行为C++程序。
C标准
说它语法错误(强调是我的(,它没有产生有效的令牌,因此程序无效:
5.2.1字符集
2/在字符常量或字符串文字中,执行字符集的成员应由源字符集的相应成员表示,或由反斜杠\后面跟着一个或多个字符组成的转义序列表示。
6.4.4.4字符常量
3/单引号'、双引号"、问号?、反斜杠\和任意整数值可根据以下转义序列表表示:
- 单引号'
'
- 双引号"
"
- 问号?
?
- 反斜杠\
\
- 八进制字符
octal digits
- 十六进制字符
xhexadecimal digits
8/此外,不在基本字符集中的字符可以用通用表示字符名和某些非图形字符可以用转义序列表示由反斜杠\后跟小写字母:\a、\b、\f、\n、\r、\t和\v组成。注意:如果反斜杠后面有任何其他字符,则结果不是标记,需要进行诊断。
C++标准
不同的说法(强调是我的(:
5.13.3字符文字
7/某些非图形字符,单引号'、双引号"、问号?、25和反斜杠\,可以根据表8表示。双引号"和问号"可以表示为它们自己,也可以用转义序列"one_answers"表示?但单引号"和反斜杠"应分别由转义序列"one_answers"表示表8中没有列出反斜杠后面的字符的转义序列是有条件支持的,具有实现定义的语义。转义序列指定单个字符。
因此,对于C++,您需要查看编译器手册以了解语义,但该程序在语法上是有效的。
您需要使用一致的C编译器进行编译。各种在线编译器倾向于使用默认设置为"宽松非标准模式"(也称为GNU C(的gcc。这可能会也可能不会启用一些非标准转义序列,但即使您违反了C语言,它也不会产生编译器错误-您可能会收到"警告",但这并不能使代码有效。
如果你告诉gcc用-std=c17 -pedantic-errors
作为一个一致的C编译器,你会得到这个错误:
error: unknown escape sequence: ' 40'
040是32的八进制,32是' '
的ASCII码。(出于某种原因,gcc内部对转义序列使用八进制表示法,可能是因为\0是八进制,我不知道为什么。(