在C ++源代码中使用Unicode

时间:2008-12-01 18:09:45

标签: c++ unicode character-encoding standards

C ++源代码的标准编码是什么? C ++标准是否甚至对此有所说明?我可以用Unicode编写C ++源代码吗?

例如,我可以在评论中使用非ASCII字符,例如中文字符吗?如果是这样,是允许完全Unicode还是只是Unicode的一个子集? (例如,16位第一页或其他任何名称。)

此外,我可以将Unicode用于字符串吗?例如:

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

8 个答案:

答案 0 :(得分:34)

C ++中的编码非常复杂。这是我对它的理解。

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

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

  

物理源文件字符是   映射,在实现定义中   方式,基本来源角色   设置(引入换行符   对于终端指标)如果   必要。 Trigraph序列(2.3)   被相应的替换   单字符内部   表示。任何源文件   字符不在基本来源中   字符集(2.2)被替换为   通用字符名称   点燃那个角色。 (一个   实施可以使用任何内部   编码,只要是实际的   遇到的扩展字符   源文件,和扩展名相同   在源文件中表示的字符   作为通用字符名称(即   使用\ uXXXX表示法,是   等价处理。)

对于gcc,您可以使用选项-finput-charset=charset进行更改。此外,您可以在运行时更改用于表示值的执行字符。适当的选项是-fexec-charset=charset用于char(默认为utf-8)和-fwide-exec-charset=charset(默认为utf-16utf-32,具体取决于wchar_t)。

答案 1 :(得分:9)

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

通常的编码是(或曾经是)7位ASCII - 一些编译器(例如Borland的编码器)会忽略使用高位的ASCII字符。如果您的编译器和编辑器接受它们,那么没有技术上的原因无法使用Unicode字符 - 大多数现代的基于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.

答案 2 :(得分:9)

除了litb的帖子,MSVC ++也支持Unicode。据我所知,它从BOM中获取Unicode编码。它绝对支持int (*♫)();const std::set<int> ∅;等代码 如果你真的陷入代码晦涩:

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

答案 3 :(得分:6)

这里有两个问题。第一个是C ++代码(和注释)中允许的字符,例如变量名。第二个是字符串和字符串文字中允许的字符。

如上所述,C ++编译器必须支持一个非常受限制的基于ASCII的字符集,用于代码和注释中允许的字符。在实践中,这个字符集对于一些欧洲字符集(特别是一些没有几个字符的欧洲键盘 - 如方括号 - 可用)效果不佳,因此有向图和三字符的概念是介绍。许多编译器目前接受的不仅仅是这个字符集,但没有任何保证。

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


C ++ 11增加了对Unicode字符串和字符串文字的明确支持,编码为UTF-8,UTF-16大端,UTF-16小端,UTF-32大端和UTF-32小端。

答案 4 :(得分:3)

对于字符串编码,我认为您打算使用 \ u 表示法,例如:

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

答案 5 :(得分:2)

值得注意的是,C ++中的宽字符并不是真正的Unicode字符串。它们只是较大字符的字符串,通常为16,但有时为32位。这是实现定义的,但IIRC你可以拥有一个8位wchar_t你对它们中的编码没有真正的保证,所以如果你试图做一些像文本处理这样的事情,你可能会想要一个将Unicode定义为最适合Unicode实体的整数类型。

C ++ 1x以UTF-8编码字符串文字(u8"text"),UTF-16和UTF-32数据类型(char16_t和{{1}的形式提供额外的unicode支持} IIRC)以及相应的字符串常量(char32_tu"text")。不使用U"text"\uxxxx常量指定的字符的编码仍然是实现定义的(并且文字之外的复杂字符串类型没有编码支持)

答案 6 :(得分:2)

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

GCC 4.1不支持此功能,但GCC 4.4支持,最新的Qt版本使用GCC 4.4,因此请使用“UTF-8 with Bom”作为源文件编码。

答案 7 :(得分:0)

AFAIK它没有标准化,因为你可以在宽字符串中放置任何类型的字符。 您只需检查您的编译器是否设置为Unicode源代码,以使其正常工作。