为啥是 ”\?” C/C++ 中的转义序列?
Posted
技术标签:
【中文标题】为啥是 ”\\?” C/C++ 中的转义序列?【英文标题】:Why is "\?" an escape sequence in C/C++?为什么是 ”\?” C/C++ 中的转义序列? 【发布时间】:2013-10-15 06:49:29 【问题描述】:在 C/C++ 中有四个特殊的非字母字符需要转义:单引号 \'
、双引号 \"
、反斜杠 \\
和问号 \?
。这显然是因为它们具有特殊的含义。 '
用于单个 char
,"
用于字符串文字,\
用于转义序列,但为什么 ?
是其中之一?
我今天阅读了教科书中的转义序列表,我意识到我之前从未转义过?
,也从未遇到过问题。可以肯定的是,我在 GCC 下对其进行了测试:
#include <stdio.h>
int main(void)
printf("question mark ? and escaped \?\n");
return 0;
还有 C++ 版本:
#include <iostream>
int main(void)
std::cout << "question mark ? and escaped \?" << std::endl;
return 0;
两个程序输出:question mark ? and escaped ?
所以我有两个问题:
-
为什么
\?
是转义序列字符之一?
为什么非转义?
可以正常工作?甚至没有警告。
更有趣的事实是转义的\?
也可以与?
在其他一些语言中一样使用。我在 Lua/Ruby 中进行了测试,即使我没有找到文档记录也是如此。
【问题讨论】:
我不确定其他编译器,但gcc
默认忽略二合字母和三合字母。
@devnull 是的,我在自己的回答中说了同样的话。 :)
后来看到了,评论了。
来自this 答案:This is why the escape sequence '\?' is recognized (as a simple question mark - though presumably that is '??/?').
【参考方案1】:
为什么
\?
是转义序列字符之一?
因为它很特别。答案导致Trigraph,C/C++ 预处理器用对应的单个字符替换下面的三个字符序列。 (C11 §5.2.1.1 和 C++11 §2.3)
Trigraph: ??( ??) ??< ??> ??= ??/ ??' ??! ??-
Replacement: [ ] # \ ^ | ~
三元组现在几乎没用了,它主要用于混淆目的。一些例子可以在IOCCC看到。
GCC 默认不支持三元组,如果代码中有三元组,它会发出警告,除非启用了选项-trigraphs
3。在-trigraphs
选项下,第二个\?
在以下示例中很有用:
printf("\?\?!\n");
如果?
未转义,则输出将为|
。
有关三合符的更多信息,请参阅Cryptic line "??!??!" in legacy code
为什么非转义
?
可以正常工作。甚至没有警告。
因为?
(和双引号"
)可以用标准自己表示:
C11 §6.4.4.4 字符常量第 4 节
双引号
"
和问号?
可以单独表示,也可以分别用转义序列\"
和\?
表示,但单引号'
和反斜杠@987654341 @ 应分别由转义序列\'
和\\
表示。
在 C++ 中类似:
C++11 §2.13.2 字符字面量第 3 节
某些非图形字符,单引号
’
、双引号"
、问号?
和反斜杠\
,可以根据表6表示。双引号"
和问号?
,可以分别表示为它们本身或转义序列\"
和\?
,但单引号’
和反斜杠\
应由转义序列\’
和\\
分别。如果反斜杠后面的字符不是指定的字符之一,则行为未定义。转义序列指定单个字符。
【讨论】:
行:For example, gcc doesn't support trigraph by default, unless the option -trigraphs is enabled. Under such options, \? is useful in some cases:
是误导。似乎是说即使你不使用-trigraphs
选项,gcc 也会将??!
解释为|
。
@devnull:许多人使用-std=c++98
或-std=c99
之类的东西禁用gnu 语言变体,因此启用三元组支持非常普遍。
双引号"
怎么能代表自己呢?如果不转义,如何在字符串中间键入双引号?
@LưuVĩnhPhúc 标准对此并不明确。我认为"
不能在字符串字面量中使用,但可以在单引号中使用'"'
或'\"'
,但'''
无效,必须使用'\''
。
我不认为三元组“现在几乎没用了”。据我了解,在生产代码中寻找三元组的任何使用的努力未能在编译器测试套件之外找到任何有意使用的三元组、三元组如何工作的演示等。这听起来更准确(可能更少外交)声明将是“一个从来没有真正有用的功能,并且一开始就不应该出现在语言中”。以上是关于为啥是 ”\?” C/C++ 中的转义序列?的主要内容,如果未能解决你的问题,请参考以下文章
为啥转义序列“\a”在 Windows 窗体应用程序中不产生声音?
为啥 UserAuthExtensions.PopulateFromMap(session, jwtPayload) 不能在 ServiceStack.Auth 中正确反序列化带有转义的 json 值