c/c++ 字符编码与标识符

说明:html

      对于比较现代的语言来说字符编码不是个大问题:java就能够使用中文做为变量名称,但对于C/C++来说却不是这样,因为历史缘由,标准和编译器厂商的实现总在不停的变化,相关编码信息究竟是如何处理的?对于想知道相关信息的新手来说是很难从现有的书籍和资料上来找到明确的答案。针对这个问题我就本身的理解并结合相关的标准试图向读者把这个问题讲清楚,因为编译器众多,因此重点就放在对标准的解释以及相关文档的说明上,具体的实验和测试请自行操做。java

  标识符(Identifer)定义(C99和C++2003中的定义是一致的,C89中没有规定universal-character-name且对标识符长度有规定,C99中不对长度做限定,C++2003规定能够是任意长度):git

Syntax windows

1 identifier: identifier-nondigit app

identifier identifier-nondigit identifier digit ide

identifier-nondigit: nondigit 函数

universal-character-name 工具

other implementation-defined characters 测试

ISO/IEC 9899:1999 (E) ui

nondigit: one of _ a b c d e f g h i j k l m n o p q r s t u v w x y z

A B C D E F G H I J K L M N O P Q R S T U V W X Y Z

digit: one of 0 1 2 3 4 5 6 7 8 9 

      从广义上来说字符编码实际上有两种,一种是multibyte,另外一种是unicode,multibyte编码对字符内容的解释取决于当前系统的区域设置,如windows下的cp936(中文编码)编码就是一种multibyte编码。unicode编码与系统的当前编码没有相关性;在各平台上都应该能正确处理;实际上与UCS编码(ISO/IEC 10646)是兼容的。unicode是一种编码方式的统称,事实上它包含多种编码如:utf-8,utf-16等。那么对于字符编码在C语言的相关标准又是怎么规定的呢?ANSI C标准(既C89)明确规定multibyte字符只能应用在字符串字面量,注释、字符常量这三个方面。对于标识符而言(变量名、函数名等)只能使用基本字符(其实是26个字母)与数字以及下划线,而且不容许以数字开头,具体的编译器至少要能正确处理31个长度的标识符名称(C89标准 5.2.1.2)。可见早期的编译器从标准角度来看是没法处理mulibyte和unicode标识符的,但实际上具体的编译器实现可能做出了扩展以容许标识符字符进行扩展,例如GNU的扩展选项-fextended-identifiers。随着标准的发展此问题获得了解决,C99标准明确规定multibyte和universal-character-name能够做为标识符的名字(C99标准 5.2.1.2)。至于C++,2003标准只规定了基本拉丁字符、数字、下划线以及universal-character-name,而multibyte由具体的编译器实现决定。可见因为标准的变化以及相关编译器的实现异差,在实际工做应该只使用基本的拉丁字符、数字、下划线用做标识符,这样才能保证可移植性。

相关编译器信息:

GNU 3.1

http://gcc.gnu.org/onlinedocs/gcc-3.1/gcc/Identifiers-implementation.html

Identifiers

  • Which additional multibyte characters may appear in identifiers and their correspondence to universal character names (6.4.2).
  • The number of significant initial characters in an identifier (5.2.4.1, 6.4.2)
  • 更早版本的相关信息无从考证了。若有疑问请自行google。

VS2003:

Visual C++ .NET 2003 Enhanced Compiler Conformance

In this version of the compiler, Unicode characters that cannot be represented in the current system code page are not allowed. The compiler's support for Unicode characters and universal-character-names, as specified in ISO/ANSI Standard, is as follows:

  • Comments

  • String and character literals

  •  

    可见在这个版本支持仍是进分有限的,不支持multibyte只支持universal-character-names 

VS2005

http://msdn.microsoft.com/zh-cn/library/vstudio/xwy0e8f2(v=vs.100).aspx

文件名

如今能够在命令行和编译器指令(如 #include)中指定的文件名中包含 Unicode 字符。 在 Visual C++ 的早期版本中,仅支持 ANSI 文件名。 在输出文件名中应避免非 ASCII 字符,以即可执行文件可在 Windows 98 和 Windows Me 的本地化版本上运行。

源代码文件

如今,标识符、宏、字符串和字符文本以及注释中均支持 Unicode 字符。 如今也支持通用字符名称。

可按如下编码格式将 Unicode 字符输入到源代码文件中:

  • 具备或不具备字节顺序标记 (BOM) 的 UTF-16 Little Endian

  • 具备或不具备 BOM 的 UTF-16 Big Endian

  • 具备 BOM 的 UTF-8

Output

在编译期间,编译器以 UTF-16 格式将诊断输出到控制台。 可在控制台显示的字符由控制台窗口属性决定。 重定向到文件的编译器输出位于当前 ANSI 控制台代码页中。

连接器响应文件和 .DEF 文件

响应文件和 DEF 文件能够是具备字节顺序标记的 UTF-16,也能够是 ANSI。 之前仅支持 ANSI。

.asm 和 .cod 转储

默认状况下,.asm 和 .cod 转储为 ANSI 格式,以便兼容 MASM。 使用 /FAu 则输出 UTF-8。 请注意,若是指定 /FAs,则将只是直接输出混合源文件,并且可能会显示为乱码,例如,当源代码为 UTF-8 而且未指定 /FAsu 时。

能够经过选择合适的工具以及选择“启用 Unicode 响应文件”属性(默认为启用)在开发环境中启用 Unicode 文件名(请参见 如何:打开项目属性页)。 有些状况下须要更改此默认值,例如要修改开发环境以便使用不具备 Unicode 支持的编译器时。

VS2005对multibyte和unicode支持的都很完善了。后继的VS2008-VS2012与VS2005在此方面基本没有差别。若是感兴趣可另行查找相关资料。

LLVM 3.3

Clang supports Unicode characters in identifiers and its static analyser has added new checkers and can run interprocedural analyses across C++ constructor/destructor boundaries.

最后

      事不辩不清,理不论不明。欢迎就此老是一块儿讨论。

相关文章
相关标签/搜索