在C ++源代码中使用Unicode

什么是C ++源代码的标准编码? C ++标准甚至会说这个吗? 我可以用Unicode编写C ++源代码吗?

例如,我可以在注释中使用非ASCII字符,例如中文字符吗? 如果是这样,是完全的Unicode允许的还是只是一个Unicode的子集? (例如,这个16位的第一页或者其他的东西)。

此外,我可以使用Unicode的string? 例如:

Wstring str=L"Strange chars: â Țđ ě €€"; 

用C ++进行编码相当复杂。 这是我的理解。

每个实现都必须支持来自基本源字符集的字符 。 这些包括§2.2/ 1(C ++ 11中的§2.3/ 1)中列出的常见字符。 这些字符应该全部适合一个char 。 此外,实现必须支持使用名称为universal-character-names的方式来命名其他字符,并且看起来像\uffff\Uffffffff ,可用于引用Unicode字符。 它们的一个子集可用于标识符(列于附件E)。

这一切都很好,但是从文件中的字符到源字符(在编译时使用)的映射是实现定义的。 这构成了使用的编码。 这就是字面意思(C ++ 98版本):

如果需要,物理源文件字符以实现定义的方式映射到基本源字符集(为行尾指示符引入新行字符)。 Trigraph序列(2.3)被replace为相应的单字符内部表示。 任何不在基本源字符集(2.2)中的源文件字符都将replace为指定该字符的通用字符名称。 (一个实现可以使用任何内部编码,只要在源文件中遇到实际的扩展字符,并且在源文件中用通用字符名称(即使用\ uXXXX表示法)表示相同的扩展字符)等效)。

对于gcc,可以使用选项-finput-charset=charset来更改它。 此外,您可以更改用于在运行时表示值的执行字符。 对于这个适当的选项是char -fexec-charset=charset (默认为utf-8 )和-fwide-exec-charset=charset (根据wchar_t的大小,缺省为utf-16utf-32 ) 。

除了litb的post之外,MSVC ++也支持Unicode。 我知道它从BOM中获取Unicode编码。 它绝对支持像int (*♫)(); 或者const std::set<int> ∅; 如果你真的陷入代码混淆:

 typedef void ‼; // Also known as \u203C class ooɟ { operator ‼() {} }; 

就我所知,C ++标准没有提到任何有关源代码文件编码的内容。

通常的编码是(或曾经是)7位的ASCII – 一些编译器(例如Borland's)会使用高位的ASCII字符。 如果你的编译器和编辑器接受它们,大多数现代的基于Linux的工具,以及许多更好的基于Windows的编辑器都可以毫无问题地处理UTF-8编码,我不确定微软的编译器会如何。

编辑:它看起来像微软的编译器将接受Unicode编码的文件,但有时也会产生8位ASCII错误:

 warning C4819: The file contains a character that cannot be represented in the current code page (932). Save the file in Unicode format to prevent data loss. 

这里有两个问题。 首先是C ++代码(和注释)允许使用哪些字符,如variables名称。 第二个是string和string中允许使用的字符。

如上所述,C ++编译器必须支持代码和注释中允许使用的字符的非常有限的基于ASCII的字符集。 在实践中,这个字符集对于一些欧洲字符集(特别是一些没有几个字符的欧式键盘 – 比如方括号 – 可用)来说效果不是很好,所以二合字母和三字符的概念是介绍。 许多编译器目前接受的不止这个字符集,但是没有任何保证。

至于string和string文字,C ++具有宽字符和宽string的概念。 但是,该字符集的编码是未定义的。 在实践中,它几乎总是Unicode,但我不认为这里有任何保证。 宽字符string文字看起来像L“string文字”,这些可以分配给std :: wstring的。


C ++ 11增加了对Unicodestring和string文字的显式支持,编码为UTF-8,UTF-16大端,UTF-16小端,UTF-32大端和UTF-32小端。

对于string中的编码,我认为你的意思是使用\ u表示法,例如:

 std::wstring str = L"\u20AC"; // Euro character 

还值得一提的是,C ++中的宽字符并不是真正的Unicodestring。 它们只是更大字符的string,通常是16,但有时是32位。 这是实现定义,但是,IIRC你可以有一个8位wchar_t你没有真正的保证,他们的编码,所以如果你正在尝试做文本处理的东西,你可能会需要一个typedef到最合适的整数types到你的Unicode实体。

C ++ 1x以UTF-8编码string文本( u8"text" ),UTF-16和UTF-32数据types( char16_tchar32_t IIRC)以及相应的string常量( u"text"U"text" )。 但是,在没有\uxxxx\Uxxxxxxxx常量的情况下指定的字符的编码仍然是实现定义的,但是(对于文字外部的复杂stringtypes没有编码支持)

在这种情况下,如果您得到MSVC ++警告C4819,只需将源文件编码更改为“带有Bom的UTF-8”。

GCC 4.1不支持,但是GCC 4.4做了,最新的Qt版本使用GCC 4.4,所以使用“UTF-8 with Bom”作为源文件编码。

AFAIK这是不规范的,因为你可以把任何types的字符在宽string。 你只需要检查你的编译器是否设置为Unicode源代码,以使其正确工作。