问题描述
#include <iostream>
#include <cstring>
int main()
{
auto l = std::strlen("123\0456\0");
std::cout << l << std::endl;
}
为什么此代码的输出为5?
我应该是3。
这里是要测试的在线版本: https://ideone.com/UQRKlV
解决方法
"123\0456\0"
是类型const char[7]
的文字。
\045
是一个字符,以八进制指定。在ASCII中为'%'
。这里的\0
不是 ,因为 munch munch 解析规则会提取NUL
作为八进制转义序列:请注意,0、4和5是有效的八进制数字,并且八进制转义序列不能超过3个数字。
第二个\045
是显式的\0
,并且在文字的末尾隐含了额外的NUL
。
NUL
将返回5,因为第一个strlen
之前有许多字符。
可以使用十六进制({{1}),八进制(\xNN
)或Unicode(\0NN
,\uNNNN
)表示法来表示文字中的字符escaped
在您的字符串文字中,\UNNNNNNNN
,"123\0456\0"
和\045
是OCTAL转义序列。
您期望编译器将第一个\0
解析为NUL终止符的1位数八进制序列,但实际上它被解析为3位数八进制序列,因为八进制最多使用3位数max,0、4和5是有效的八进制数字。因此,编译器会将3位数的\0
序列解析为单个\045
,其数值为八进制45(十进制37,十六进制0x25),该值在 most 中(不是all)字符集是ASCII char
字符,它将解析第二个1位数%
序列为单个\0
,其数值为八进制0(十进制0,十六进制0x00) ,在所有字符集中都是char
字符。
因此,NUL
总共有7个"123\0456\0"
(包括末尾的隐式空终止符):
char
1 2 3 % 6 NUL NUL
将计数strlen()
,直到遇到char
字符为止。这就是为什么输出为5而不是3的原因。
首先了解string literals in C++。寻找escape sequences的特殊含义。
然后阅读strlen的内容,并结合这些知识来解释结果。