Mar*_*son 39 c++ portability c++11
如果我有一个多行字符串C++ 11字符串常量,如
R"""line 1
line 2
line3"""
Run Code Online (Sandbox Code Playgroud)
它是否定义了行终止符/分隔符由哪些字符组成?
Kei*_*son 27
目的是将原始字符串文字中的换行符映射到单个
'\n'字符.这种意图没有表现得如此清晰,这导致了一些混乱.
引文符合2011 ISO C++标准.
首先,这是它映射到单个'\n'字符的证据.
第2.14.5节[lex.string]第4段的说明如下:
[ 注意:原始字符串文字中的源文件换行会在生成的执行字符串文字中生成换行符.假设在以下示例中的行的开头没有空格,则断言将成功:
const char *p = R"(a\
b
c)";
assert(std::strcmp(p, "a\\\nb\nc") == 0);
Run Code Online (Sandbox Code Playgroud)
- 结束说明 ]
这清楚地表明换行符映射到单个'\n'
字符.它还匹配观察到的g ++ 6.2.0和clang ++ 3.8.1的行为(使用具有Unix风格和Windows风格的行结尾的源文件在Linux系统上完成的测试).
鉴于笔记中明确表达的意图以及两个流行编译器的行为,我认为依赖于此是安全的 - 尽管看看其他编译器如何实际处理它会很有趣.
然而,对标准的规范性措辞的字面解读很容易导致不同的结论,或者至少是一些不确定性.
第2.5节[lex.pptoken]第3段说(重点补充):
在原始字符串的初始和最终双引号字符之间,在阶段1和2中执行的任何转换 (三字符,通用字符名称和行拼接) 都将被还原; 在确定任何d-char, r-char或分隔括号之前,应该应用此反转.
翻译阶段在2.2 [lex.phases]中指定.在第1阶段:
如果需要,物理源文件字符以实现定义的方式映射到基本源字符集(引入行尾指示符的换行符).
如果我们假设物理源文件字符到基本字符集的映射和换行符的引入是" 转换 ",我们可以合理地得出结论,例如,在原始字符串文字中间的换行符Windows格式的源文件应该等同于\r\n序列.(我可以想象对特定于Windows的代码有用.)
(这种解释确实导致系统出现问题,其中行尾指示符不是字符序列,例如每行是固定宽度的记录.这些系统现在很少见.)
正如"干杯和赫斯 - 阿尔夫"的答案 指出的那样, 这个问题有一个公开的 缺陷报告.它于2013年提交,尚未得到解决.
就个人而言,我认为混淆的根源是"任何"一词(强调如前所述):
在原始字符串的初始和最终双引号字符之间,在阶段1和2中执行的任何转换(三字符,通用字符名称和行拼接)都将被还原; 在确定任何d-char,r-char或分隔括号之前,应该应用此反转.
当然,物理源文件字符到基本源字符集的映射可以合理地被认为是转换.带括号的子句"(三字符,通用字符名称和行拼接)"似乎旨在指定要还原哪些转换,但是要么试图改变"转换"一词的含义(标准所做的)没有正式定义)或与"任何"一词的使用相矛盾.
我建议将"任何"改为"确定"将更清楚地表达明显的意图:
在原始字符串的初始和最终双引号字符之间,恢复在阶段1和2中执行的某些转换(三字符,通用字符名称和行拼接); 在确定任何d-char,r-char或分隔括号之前,应该应用此反转.
这一措辞将使"三字母,通用字符名称和行拼接"成为唯一需要恢复的转换更加清晰.(并非所有在翻译阶段1和2中完成的操作都会被还原,只是那些特定的列出的转换.)
R S*_*ahu 16
该标准似乎表明:
R"""line 1
line 2
line3"""
Run Code Online (Sandbox Code Playgroud)
相当于:
"line 1\nline 2\nline3"
Run Code Online (Sandbox Code Playgroud)
从2.14.5 C++ 11标准的字符串文字:
4 [ 注意:原始字符串文字中的源文件换行符会在生成的执行字符串文字中生成换行符.假设在以下示例中的行的开头没有空格,则断言将成功:
Run Code Online (Sandbox Code Playgroud)const char *p = R"(a\ b c)"; assert(std::strcmp(p, "a\\\nb\nc") == 0);- 结束说明 ]
5 [ 示例:原始字符串
Run Code Online (Sandbox Code Playgroud)R"a( )\ a" )a"相当于
"\n)\\\na\"\n".
注意:自答案发布以来,问题已发生重大变化.只剩下一半,即纯C++方面.本回答中的网络焦点解决了原始问题的"将多行字符串发送到具有明确定义的行尾要求的服务器".我不追求一般的问题进化.
在程序内部,换行的C++标准是\n.这也用于原始文字中的换行符.原始文字没有特殊约定.
通常\n映射到ASCII换行符,即值10.
我不确定它在EBCDIC中映射到了什么,但是如果需要你可以检查一下.
然而,在线上,我的印象是大多数协议使用ASCII回车加换行,即13后跟10.这有时称为CRLF,在回车的ASCII缩写CR和换行的LF之后.当C++转义符映射到ASCII时,这只是\r\n在C++中.
您需要遵守您正在使用的协议的要求.
对于普通的文件/流i/o,C++标准库负责将内部映射\n到主机环境使用的任何约定.这称为文本模式,与不执行映射的二进制模式相反.
对于标准库未涵盖的网络i/o,应用程序代码必须直接或通过某些库函数自行完成.
关于这个核心语言缺陷报告#1655 "原始字符串文字中的行结尾" 存在一个活跃的问题,由迈克米勒2013-04-26提交,他在那里问道,
"例如,它是否打算将原始字符串文字源中的CRLF表示为换行符或原始字符?
由于行结束值因原始文件的编码而不同,并且考虑到在某些文件系统中没有行结尾的编码,而是作为记录的行,显然意图不是表示文件内容 -是 - 因为在所有情况下都不可能做到这一点.但据我所知,这个DR尚未解决.
| 归档时间: |
|
| 查看次数: |
2572 次 |
| 最近记录: |