我的源字符串使用哪种编码
Which encoding are my source strings in?
当我有这样的C++代码时:
std::string narrow( "This is a narrow source string" );
std::string n2( "Win-1252 (that's the encoding we use for source files): ä,ö,ü,ß,€, ..." );
// What encoding should I pass to Win32's `MultiByteToWideChar` function
// to convert these string to a propoer wchar_t (= UTF-16 on Windows)?
如果这是我们的cpp文件的(隐式)编码,我可以一直假设Win-1252吗?VisualC++编译器如何决定编码源文件的字符?
例如,如果开发人员使用一台"正常"文本文件默认为另一个单字节/多字节编码的机器,会发生什么?
我认为编码只是用于编译代码的机器上的一个问题?也就是说,一旦构建了可执行文件,无论用户PC上的语言/区域设置如何,将静态字符串从固定的窄编码转换为Windows的UTF-16 wchar_t都将始终产生相同的结果?
注意:由于编写了下面的答案,VC++为源代码和执行字符集编码添加了额外的选项。请参见此处。
对于宽字面值,VC++将始终产生UTF-16,而对于窄字面值,VC++将始终从源编码转换为"UTF-16";为非Unicode程序编码";在主机(运行编译器的系统)上设置。因此,只要VC++正确识别源代码,就会得到UTF-16和非Unicode程序的编码。
为了确定源编码,VC++检测所谓的BOM。它将识别UTF-16和UTF-8。如果没有BOM,则假定源代码是使用非Unicode程序的系统编码进行编码的。
如果这导致使用了错误的编码,那么编译器对字符和字符串文字执行的任何转换都将导致ASCII范围之外的任何字符的值错误。
一旦程序被编译,那么是的,只要这些编译时转换进行,区域设置就会停止,因为数据是静态的。
不过,编码可能对其他事情很重要,比如将其中一个字符串打印到控制台。您必须对控制台正在使用的任何内容执行适当的转换,或者确保控制台设置为接受您正在使用的编码。
关于#pragma setlocale
的注释
#pragma setlocale
只影响到宽文本的转换,它既不通过设置源编码也不通过更改宽执行编码来实现。坦率地说,它的实际作用是可怕的。举个例子,以下断言失败:
#pragma setlocale(".1251")
static_assert(L'Я' != L'ß', "wtf...");
如果您对源代码使用任何Unicode编码,则绝对应该避免这种情况。
语言规范只是说源字符是以实现定义的方式映射的。您需要查阅正在使用的编译器的文档,以便了解该实现的定义。例如,Microsoft Visual C++使用#pragma setlocale
来指定代码页。
- 将C++ std::string 转换为 UTF-16-LE 编码的字符串
- 使用文件内容作为硬编码字符串
- 协议缓冲区字符串字段的文本编码
- 如何在 c++ 中读取用 utf-8 编码的 java unicode 字节字符串
- 硬编码字符串与强制转换为 PUCHAR 并打印到控制台时从控制台读取的字符串的结果不同
- 替换 Qt C++ 中编码字符串的"="
- 从相同的硬编码字符串文字初始化std::string和std::wstring
- C++ 避免 if 和硬编码字符串
- 将字节数组转换为编码字符串
- 如何在 openSSL 中将 DER 编码字符串的向量转换为 x509
- 在C++中加密硬编码字符串的最佳方法是什么
- 初始化 utf8 编码字符串 c++11
- 当使用L前缀(Visual C++编译器)时,如何#定义硬编码字符串
- 在空白字符上拆分 UTF-8 编码字符串,而无需了解 UTF-8 编码
- 为什么Debian和AS400给出不同的base64编码字符串
- 来自终端的Base64编码字符串
- C++ "cannot add two pointers" ,将硬编码字符串添加到 CString
- 处理std::wstring和std::string之间的UTF-8编码字符串
- 编码字符串和解码字符串的差异
- 需要帮助编码c++字符串增加ASCII值