MSVC++中源字符集编码规范,类似于gcc的“-finput-charset = CharSet”参数。

17

我想创建一些处理编码的示例程序,具体来说,我想使用宽字符串,例如:

wstring a=L"grüßen";
wstring b=L"שלום עולם!";
wstring c=L"中文";
因为这些是示例程序。
对于将源代码视为UTF-8编码文本的gcc来说,这是绝对微不足道的问题。但是,在MSVC下,直接编译可能会出现问题。我知道可以使用转义序列对它们进行编码,但我更喜欢将它们保留为可读文本。
是否有任何选项可以作为命令行开关在“cl”中指定,以使其正常工作?是否有类似于gcc的-finput-charset的命令行开关?
如果没有,您会建议如何使文本对用户更加自然?
注意:将BOM添加到UTF-8文件不是一个选择,因为其他编译器将无法编译它。
注意2:我需要它能在MSVC版本> = 9 == VS 2008中工作。
真实答案:没有解决方案。

3
太惊人了,MSVC++ 竟然没有这样的编译选项。真是遗憾啊... - Piotr Dobrogost
我猜您在问这个问题时指的是源文件字符集的规范,请更正我如果我猜错了。“源字符集”是标准中用于编译器内部使用的实现定义字符集的术语。 - Piotr Dobrogost
1
@PiotrDobrogost 任何人都无法猜测为什么微软没有跟上世界其他地区的步伐,本地支持UTF-8编译和SDK,并在程序员必须将Windows应用国际化到UTF-8世界中时添加了如此多的低效、麻烦、混乱和痛苦。但我有一个猜测;这叫做官僚主义利润动机,而不是对质量的关心或关注。 - Dan Nissenbaum
2
@DanNissenbaum,你看,微软故意不支持UTF-8或任何真正的“互操作性”(这个术语是他们发明的)。有很多地方微软只是把东西搞得勉强能用。所以要么按照微软的方式,要么就没有其他选择。 - Artyom
5个回答

18
对于那些奉行“迟到总比不来得好”的人来说,Visual Studio 2015(编译器的第19个版本)现在支持此功能。
新的/source-charset命令行开关允许您指定用于解释源文件的字符集编码。它需要一个参数,可以是IANA或ISO字符集名称之一:
/source-charset:utf-8

或特定代码页的十进制标识符(前缀为点号):
/source-charset:.65001

官方文档在这里, Visual C++ 团队博客上也有一篇详细的文章描述了这些新选项

还有一个互补的/execution-charset开关, 它的作用方式完全相同,但控制着可执行文件中生成的窄字符和字符串字面值。最后,还有一个快捷开关/utf-8, 它设置了/source-charset:utf-8/execution-charset:utf-8两个选项。

这些命令行选项与旧的#pragma setlocale#pragma execution-character-set指令不兼容,并且它们适用于所有源文件。

对于使用旧版本编译器的用户,最好的选择仍然是将源文件保存为带有BOM的UTF-8格式(正如其他答案所建议的,IDE在保存时可以执行此操作)。编译器将自动检测并适当地处理此格式。GCC也接受源文件开头的BOM,不会因此而出错,使这种方法具有功能上的可移植性。

8

打开文件 - > 高级保存选项...在编码组合框中选择Unicode(带签名的UTF-8) - 代码页65001。编译器将自动使用所选编码。


根据Microsoft的回答这里:

如果您想要非ASCII字符,那么“官方”的可移植方法是使用\u(或\U)十六进制编码(我同意,这只是纯粹丑陋和容易出错的)。

当编译器面对没有BOM的源文件时,编译器会向前读取一定距离的文件以查看是否可以检测到任何Unicode字符 - 它特别寻找UTF-16和UTF-16BE - 如果两者都没有找到,则假设其具有MBCS。 我怀疑在这种情况下它会退回到MBCS,这就是问题的根源。

明确最好,因此虽然我知道这不是完美的解决方案,但我建议使用BOM

乔纳森·卡夫斯
Visual C++编译器团队。


将文本字符串放置在资源文件中是一个好的解决方法。 这是一种便捷且可移植的方法。 您可以使用本地化库,如gettext来管理翻译。


编译器会自动将文件中的字符串常量转换,因此字符串将以UCS2编码形式存储在EXE中。 - Kirill V. Lyadvinsky
好的,我明白了,你的意思是建议手动将“BOM”标记添加到UTF-8中,确实可以解决问题,但问题是它不能与gcc和其他不需要无意义BOM的编译器一起使用。 - Artyom
也许你应该尝试不带签名的UTF-16编码。Visual C++支持它,那gcc呢? - Kirill V. Lyadvinsky
没有编译器可以解释所有的代码,所以最好选择适合你的编译器。 - Artyom
1
好的...我看到微软已经回答说没有解决方案。感谢提供参考,接受答案。 - Artyom

2
我们所采用的流程为:将文件保存为UTF8带BOM格式,使得linux和windows共享相同的源文件。对于linux系统:在编译指令中预处理源文件以删除BOM,并在非BOM文件上运行g++作为中间文件。

1

在我看来,所有的C++源文件都应该是严格的ASCII格式。如果编辑器支持,注释可以使用UTF-8格式。
这样可以使代码跨平台、编辑器和源代码控制系统具有可移植性。

您可以使用\u将Unicode字符插入到宽字符串中:

std::wstring str = L"\u20AC123,00"; //€123,00

5
那恰恰是我不想做的。 - Artyom

1

如果你使用的是VS,可以使用以下方法:

#pragma setlocale( "[locale-string]" )

文件编码将使用区域设置的默认 ANSI 代码页。

但通常在代码中硬编码任何用户可见字符串都是一个不好的主意。将它们存储在某种资源中。这对本地化、易于拼写检查和更新等方面都很有好处。


一般来说,在您的代码中硬编码任何用户可见字符串都是一个不好的主意。我知道,但这大多是为了例子,在这些情况下,让用户看到发生了什么很重要。但是,我该如何在区域设置字符串中指定UTF-8字符集呢?据我所知,Windows不支持UTF-8编码的区域设置。 - Artyom
经过简短的测试,MSVC 2005 无法接受 setlocale(".65001") 即 UTF-8 代码页。 - Artyom
65001是一个代码页,pragma需要一个locale。 没有UTF-8作为代码页的locale。如果你只需要在VS中工作,你可以将它保存为UTF-16 (从记事本中“另存为”并选择编码“Unicode”)否则,唯一可移植的方法是像Sherwood Hu建议的那样进行转义。不管你喜不喜欢,这是唯一的方法。而正确的方法是不要在你的c文件中硬编码它 :-) - Mihai Nita

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