61

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

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

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

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

8 回答 8

37

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

每个实现都必须支持来自基本源字符集的字符。其中包括第 2.2/1 节(C++11 中的第 2.3/1 节)中列出的常见字符。这些字符都应该合而为一char。此外,实现必须支持一种命名其他字符的方法,该方法使用名为universal-character-namesand look like \uffffor \Uffffffffand 的方式来指代 Unicode 字符。它们中的一个子集可用于标识符(在附件 E 中列出)。

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

如有必要,物理源文件字符以实现定义的方式映射到基本源字符集(为行尾指示符引入换行符)。三元字符序列(2.3)被相应的单字符内部表示代替。任何不在基本源字符集 (2.2) 中的源文件字符都将替换为指定该字符的通用字符名。(实现可以使用任何内部编码,只要处理源文件中遇到的实际扩展字符,以及源文件中表示为通用字符名称的相同扩展字符(即使用 \uXXXX 表示法)等价的。)

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

于 2008-12-01T19:38:42.700 回答
11

据我所知,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.
于 2008-12-01T18:26:21.443 回答
10

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

typedef void ‼; // Also known as \u203C
class ooɟ {
    operator ‼() {}
};
于 2008-12-03T15:03:03.270 回答
6

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

如前所述,对于代码和注释中允许的字符,C++ 编译器必须支持非常受限的基于 ASCII 的字符集。在实践中,这个字符集不能很好地与一些欧洲字符集(尤其是一些没有几个字符的欧洲键盘——比如方括号——可用)配合使用,所以二合字母和三合字母的概念是介绍了。许多编译器此时接受的字符集不止这个字符集,但没有任何保证。

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


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

于 2008-12-02T00:14:49.227 回答
5

对于字符串中的编码,我认为您应该使用\u表示法,例如:

std::wstring str = L"\u20AC"; // Euro character
于 2008-12-01T18:26:42.130 回答
3

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

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

于 2008-12-01T19:51:50.647 回答
2

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

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

于 2012-08-23T03:10:58.187 回答
0

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

于 2008-12-01T18:27:16.683 回答