C源文件本身是普通的文本文件,既然是文本文件,那他就有自己的字符编码格式。
我们常用的大概是GBK、UTF-8这两种格式。
如果一个utf-8格式的文本文件,是用微软的记事本程序创建的,那么这个文件的开头会有3个字节的UTF-8签名(EF BB BF),也叫做BOM。
BOM是个可选的东东,因此不是所有编辑器程序都会在文件前面加上这东东。
有些程序不识别BOM,把他当正常字符数据处理,就出错了。
好了,接下来看看字符编码对各种事情的影响。
一、C源文件的编码格式
gcc编译C源代码,默认采用utf-8编码处理输入的C源文件。如果C源文件编码格式不是utf-8,则可以通过-finput-charset选项指出源文件编码格式。
否则的话,可能会导致编译失败。
例如,假如源文件a.c是GBK格式,也可以通过如下命令编译此文件。
gcc -c -finput-charset=GBK a.c
当出现编译失败时,可以通过MadEdit这个文本编辑器打开源文件,看看他的编码格式到底是什么。
MadEdit工具非常好用,通过他可以手动切换编码格式来解析文本文件。
当我们看到显示出的内容不再是乱码时,就知道文件的编码格式了。
同时,通过选择16进制模式,还能看到每个字符的实际编码值。
通过使用16进制模式,加上手动切换编码格式,我们甚至可以查看目标文件中的字符串常量的值,及其编码格式。
二、目标文件中字符串常量的编码格式
不管C源文件是什么编码格式,gcc生成的目标文件中,对于字符串常量的值,默认总是采用utf-8编码。当然,我们也可以通过编译选项,指定生成的目标文件中字符串常量值的编码格式。例如,通过如下命令,指定为GBK格式。
gcc -c -fexec-charset=GBK a.c
通过 iconv --list ,可以查看gcc支持的编码格式。
三、程序运行时,输入输出涉及的编码格式
程序运行时,通过printf向终端输出一串字符。printf内部最终实际上是调用write系统调用,将字符串数据到描述符1,描述符1即终端设备。至于能否正常显示,那就要看所写字符串的编码格式与当前终端设备支持的编码格式是否一致了。
Linux系统的终端,默认编码格式可能是utf-8。
如果是通过SecureCRT连接到Liux,那么这就是伪终端。此时,write系统调用将字符串数据通过socket连接发给了SecureCRT程序。此时,SecureCRT就是终端设备。
如果SecureCRT上出现了乱码,可以在SecureCRT中,打开此连接的session options界面,选择terminal,Appearance,fonts,Character encoding,将这个值设置为write系统调用所写的字符串数据的编码格式即可。
printf语句,所输出的字符串,其值可能来自字符串常量,可能来自文本文件,可能来自网络。来自哪里不要紧,总之,要搞清楚数据源的编码格式。
四. windows与Linux对拷文件后,文件名乱码问题
文件名、目录名,也是文本,当然也有自己的编码格式。
不过,这些文本数据,是属于文件系统的数据,归文件系统管理。
这里的编码策略,与文件系统风格有关,与操作系统风格也有关,因此就难以说清了^_^