3

当我有这样的 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 吗?Visual-C++ 编译器如何决定源文件的字符编码?

例如,如果开发人员使用一台机器,其中“普通”文本文件默认为另一种单/多字节编码,会发生什么?

我假设编码只是用于编译代码的机器上的一个问题?也就是说,一旦构建了可执行文件,将静态字符串从固定的窄编码转换为 Windows 的 UTF-16 wchar_t 将始终产生相同的结果,而不管用户 PC 上的语言/区域设置如何?

4

2 回答 2

5

注意:由于编写了以下答案,VC++ 为源和执行字符集编码添加了额外的选项。见这里


对于宽文本 VC++ 将始终生成 UTF-16,对于窄文本 VC++ 将始终从源编码转换为主机(运行编译器的系统)上设置的“非 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 编码,则绝对应该避免这种情况。

于 2012-11-29T14:37:18.567 回答
3

语言规范只是说源字符以实现定义的方式映射。您需要查阅您正在使用的编译器的文档,以了解该实现的定义所说的内容。例如,Microsoft Visual C++ 用于#pragma setlocale指定代码页。

于 2012-11-29T14:23:23.430 回答