C++字符串字面值转义字符的规则

52

转义字符\在字符串文本中的规则是什么? 是否有所有被转义的字符的列表可供参考?

特别地,当我在gedit中使用\作为字符串字面值的一部分,后面跟着任意三个数字时,它们会以不同的颜色显示。

我试图创建一个由字符0紧随空字符(\0),再紧随字符0的字面量构造的std::string。但是,语法高亮警告我,也许这会创建类似于字符0后面跟着空字符(\00, 即\0),这意味着只有两个字符。

对于解决这个问题,这是否是最好的方法:

std::string ("0\0" "0", 3)  // String concatenation 

那么在字符串字面值中转义字符的作用有没有一些参考资料呢?例如,'\a'代表什么?


相关内容,请参考如何转义转义序列。最好的解决方案是像您之前做的那样使用串联。 - MPelletier
如果你需要一个单独的 \,只需使用 \\ - MPelletier
看起来我也可以使用初始化列表语法:std::string { '0', 0, '0' }; - David Stone
1
我不仅可以使用初始化列表语法,而且现在强烈推荐它来构造字符串,而不是使用需要指定大小或使用转义字符的任何其他方法。请考虑 https://dev59.com/yXVC5IYBdhLWcg3w2lCI#12884464 中概述的微妙未定义行为。 - David Stone
2
我现在意识到我在1:32发表的评论完全晦涩难懂...我不知道自己当时想表达什么... - MPelletier
6个回答

89
控制字符:

(十六进制码假定采用 ASCII 兼容字符编码。)

  • \a = \x07 = 警告声(响铃)
  • \b = \x08 = 退格
  • \t = \x09 = 水平制表符
  • \n = \x0A = 换行(或换行符)
  • \v = \x0B = 垂直制表符
  • \f = \x0C = 换页
  • \r = \x0D = 回车
  • \e = \x1B = 转义(非标准 GCC 扩展)
标点字符:
  • \" = 引号(对于 '"' 不需要反斜杠)
  • \' = 撇号(对于 "'" 不需要反斜杠)
  • \? = 问号(用于避免三字母组合)
  • \\ = 反斜杠
数字字符引用:
  • \ + 最多 3 个八进制数字
  • \x + 任意数量的十六进制数字
  • \u + 4 个十六进制数字(C++11 中的 Unicode BMP)
  • \U + 8 个十六进制数字(C++11 中的 Unicode 星位面)

\0 = \00 = \000 = 空字符的八进制转义

如果您确实想在 \0 后面放置一个实际的数字字符,那么是的,我建议使用字符串连接。请注意,文字字面量部分之间的空格是可选的,因此您可以写成 "\0""0"


18
\x的情况下,十六进制数字将被“贪婪地”读取,直到遇到第一个非十六进制数字(即不仅限于2个数字,这可能是您所期望的,并且正如某些语法高亮器*假定)。您可以使用@dan04的技巧来通过分割字符串来标记十六进制的结束:“\x0020”“FeedDadBeer”,而不是“\x0020FeedDadBeer”。 - Rhubbarb
那么,\x后跟奇数个十六进制数字表示什么?人们假设对于偶数个数字,每个数字代表一个从高到低顺序的半字节内存,因此\x5f01011111而不是11110101;但这是否意味着\x501010000而不是00000101?那么\x5f5又是什么呢?是01011111 01010000还是01011111 00000101 - eggyal
1
我不知道这是否足以成为一个问题,但我从某个来源收到了带有 "\e" 的字符串数据。我没有在任何参考资料中看到它,它是否等同于 \x1B - Stijn Sanders
3
不在 C 或 C++ 标准中,但一些编译器使用 \e 表示转义字符 \x1B。我已将其添加到我的列表中。 - dan04
你能提供一下关于\u\U的使用参考吗?它们可以正常工作,我对此很感兴趣,但是《C++ Primer第五版》没有提到它们。我只在Stack Overflow上找到了一两个问答涉及到它们。 - Rick

4

如果\0后面跟着其他数字,它将被解释为八进制转义序列,因此\00将被解释为单个字符。 (在C中,\0技术上也是八进制转义序列)。

您正在进行的方式:

std::string ("0\0" "0", 3)  // String concatenation 

这个构造函数接受一个char数组,所以它能够正常工作;如果你尝试只传递"0\0" "0"作为const char*,它会把它视为C字符串,并且只复制到空字符为止。
这里是转义序列列表

4

\a 是响铃/警报字符,在某些系统上会触发声音。 \nnn 表示八进制中的任意ASCII字符。然而,\0 是特殊的,因为它代表空字符,无论如何。

回答您最初的问题,您也可以将 '0' 字符转义为:

std::string ("\060\000\060", 3);
< p >(因为ASCII '0'在八进制中是60)< /p > < p >微软开发者网络(MSDN)文档非常详细地介绍了这个问题,还有cppreference网站也提供了相关信息(链接)(链接)。< /p >

那个例子使用构造函数 string (const char * s),它将 s 视为 C 字符串。OP 的例子使用 string (const char * s, size_t n) 构造函数,它将其视为字符数组。 - mgiuffrida

1
我在评论中留下了类似这样的内容,但我觉得它可能需要更多的关注,因为没有一个答案提到这种方法:
我现在更喜欢使用C++11的初始化列表特性来初始化std::string,尤其是对于非打印字符和嵌入式空字符。
std::string const str({'\0', '6', '\a', 'H', '\t'});

我不需要手动计算使用的字符数,因此如果以后我想在中间插入'\013',我可以这样做,而我的所有代码仍将正常工作。它还完全避免了意外使用错误转义序列的任何问题。

唯一的缺点是所有那些额外的',字符。


0

通过用户定义字面量的魔力,我们又有了另一种解决方案。C++14添加了一个std::string字面量运算符。

using namespace std::string_literals;
auto const x = "\0" "0"s;

构造一个长度为2的字符串,其中包含一个'\0'字符(空字符)和一个'0'字符(数字零)。我不确定它是否比initializer_list<char>构造函数方法更清晰,但至少可以摆脱',字符。


0

ascii 是一个可以在 Linux 上下载的软件包。 例如: sudo apt-get install ascii ascii

Usage: ascii [-dxohv] [-t] [char-alias...]
-t = one-line output  -d = Decimal table  -o = octal table  -x = hex table
-h = This help screen -v = version information
Prints all aliases of an ASCII character. Args may be chars, C \-escapes,
English names, ^-escapes, ASCII mnemonics, or numerics in decimal/octal/hex.`

这段代码可以帮助你处理C/C++转义字符,例如\x0A


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接