说明:

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

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

Syntax

1 identifier: identifier-nondigit

identifier identifier-nondigit identifier digit

identifier-nondigit: nondigit

universal-character-name

other implementation-defined characters

ISO/IEC 9899:1999 (E)

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.

最后

事不辩不清,理不论不明。欢迎就此总是一起讨论。

c/c++ 字符编码与标识符的更多相关文章

  1. 字符集与字符编码 (charset & encoding)

    乱码是个大坑,相信每个人都遇过,而且是个绕不过去的坑.我理解每个程序员都应该写一篇编码相关的博文,梳理自己对这一块的理解,下面是我反复理解多次之后的学习小结. 1.从记事本的不同编码说起: 打开记事本 ...

  2. .NET Framework 中的字符编码

    字符是可用多种不同方式表示的抽象实体. 字符编码是一种为受支持字符集中的每个字符进行配对的系统,配对时使用的是表示该字符的某些值. 例如,摩尔斯电码是一种为罗马字母表中的每个字符进行配对的字符编码,配 ...

  3. JAVA的字符编码及问题

    web开发时,字符编码及有时候也会是一个麻烦的问题,没有经验的话,肯定不知道怎么解决,有一定的经验的话,那还是比较简单的.以下,是我学习过程中总结出来的几种字符编码级问题和其解决的方法 1.文档乱码, ...

  4. Python第二天 变量 运算符与表达式 input()与raw_input()区别 字符编码 python转义符 字符串格式化 format函数字符串格式化 帮助

    Python第二天  变量  运算符与表达式  input()与raw_input()区别  字符编码  python转义符  字符串格式化  format函数字符串格式化  帮助 目录 Pychar ...

  5. Python 字符编码及其文件操作

    本章节内容导航: 1.字符编码:人识别的语言与机器机器识别的语言转化的媒介. 2.字符与字节:字符占多少个字节,字符串转化 3.文件操作:操作硬盘中的一块区域:读写操作 注:浅拷贝与深拷贝 用法: d ...

  6. Python编程Day7——字符编码、字符与字节、文件操作

    一.字符编码 重点 ***** 1. 什么是字符编码:将人识别的字符转换计算机能识别的01,转换的规则就是字符编码表2. 常用的编码表:ascii.unicode.GBK.Shift_JIS.Euc- ...

  7. day 07 字符编码

    一:字符编码 1.字符编码 什么是字符编码:将人能识别的字符转换为计算机能识别的01二进制的过程就是字符编码,转换的规则就是字符编码表 常用的编码表:ASCII.GBK.Unicode.UTF-8 了 ...

  8. DAY07、字符编码和文件操作

    一.字符编码 1.什么是字符编码? 人类能识别的是字符等高级标识符,电脑只能识别0,1组成的标识符,要完成人与机器之间的信息交流,              一定需要一个媒介,进行两种标识符的转化(两 ...

  9. Python之字符编码与文件操作

    目录 字符编码 Python2和Python3中字符串类型的差别 文件操作 文件操作的方式 文件内光标的移动 文件修改 字符编码 什么是字符编码? ''' 字符编码就是制定的一个将人类的语言的字符与二 ...

随机推荐

  1. AMD 规范

    AMD(异步模块定义)是为浏览器环境设计的,因为 CommonJS 模块系统是同步加载的,当前浏览器环境还没有准备好同步加载模块的条件. AMD 定义了一套 JavaScript 模块依赖异步加载标准 ...

  2. UML类图与类的关系详解【转】

    在画类图的时候,理清类和类之间的关系是重点. 类的关系有泛化(Generalization).实现(Realization).依赖(Dependency)和关联(Association).其中关联又分 ...

  3. 浅谈Manacher

    \(Manacher\)是由一个叫做\(Manacher\)的人发明的能在\(O(n)\)时间内找出一个字符串长度最长的回文子串的算法. 由于偶回文串形如\(abba\)这样的不好找对称中心,所以我们 ...

  4. Python 函数之函数调用

    Python内置了很多有用的函数,我们可以直接调用. 要调用一个函数,需要知道函数的名称和参数,比如求绝对值的函数abs,只有一个参数.可以直接从Python的官方网站查看文档: http://doc ...

  5. 使用批处理自动发布IIS站点,基于IIS7及以上

    经过研究,终于使用批处理解决了站点发布步骤多的问题. 完整批处理如下: @set "sitePath=%~dp0" @echo 新建程序池 @C:\Windows\System32 ...

  6. java的reflection和introspector

    JAVA反射机制是在运行状态中,对于任意一个类,都能够得到这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制 ...

  7. python startswith与endswith

    如果你要用python匹配字符串的开头或末尾是否包含一个字符串,就可以用startswith,和endswith比如:content = 'ilovepython'如果字符串content以ilove ...

  8. svn使用技巧一:更新、提交、资源库同步之间区别

    提交:是用本地文件覆盖服务器的文件,只有提交会导致服务器上发生变化 更新:只是把服务器上最新版本下载到客户端,规则如下: 1.如果你本地的某个文件没有修改过,而服务器上的这个文件别人已经提交过新版本, ...

  9. SpringBoot外部配置

    Spring Boot的配置文件 Spring Boot使用一个全局的配置文件application.properties或者application.yml(yaml语言的配置文件),放置在src/m ...

  10. MVC5网站部署到IIS7

    server 2008R2+IIS7.5下配置不会出现什么问题,这里记录下在server2008+IIS7下的配置 参考了一下:http://www.cnblogs.com/fcu3dx/p/3773 ...