`

C++字符集问题终极分析(转)

 
阅读更多

C++字符集问题终极分析(转)  

 
 
系统环境 
操作系统                     Windows XP 
本地字符集(MBCS) GBK 
编译器:                     VC8、VC6、DEV-C++(gcc) 
实验字符 
‘我’ 
GBK              字符编码 0xD2CE 
UNICODE     字符编码 0x6211 
‘a’ 
GBK              字符编码 0x61 
UNICODE     字符编码 0x0061 
A-源代码层面 
VC8 
1.         文件首两个字节为 0xFF 0xFE(文本文件开头几个字节标识了源文件使用的字符集,开头为0xFF 0xFE表示使用的是UNICODE字符集),所以源文件以UNICODE方式保存,‘我’字符编码为0x6211,‘a’字符编码为0x0061; 
VC6 
1.         使用本地字符集GBK保存源程序,‘我’字符编码为0xD2CE,‘a’字符编码为0x0061; 
DEV-C++(gcc) 
1.         使用本地字符集GBK保存源程序,‘我’字符编码为0xD2CE,‘a’字符编码为0x0061; 
B-可执行程序层面(源程序字符集->可执行程序字符集) 
VC8 
1.         VC8编译器默认的程序字符集是本地字符集GBK。 
2.         编译参数#pragma setlocale(LOC)告诉编译器源代码字符集为LOC,如果不设置则为UNICODE。 
3.         如果字符字面量前有L(L”我”,L”a”),并且设置了编译参数#pragma setlocale(LOC),那么编译时将发生LOC->UNICODE字符集的转换;假如没有设置则发生源代码字符集UNICODE->UNICODE的转换(相当于不发生转换),’我’的编码是0x6211,’a’的编码是0x0061。 
4.         如果字符字面量前没有L,编译时发生源代码字符集UNICODE->本地字符集GBK编码的转换,’我’的编码是0xD2CE,’a’的编码是0x61。 
VC6 
1.         VC6编译器默认的程序字符集是本地字符集GBK。 
2.         编译参数#pragma setlocale(LOC)告诉编译器源代码字符集为LOC,如果不设置则为系统默认字符集GBK。 
3.         如果字符字面量前有L(L”我”,L”a”),并且设置了编译参数#pragma setlocale(LOC),那么编译时将发生LOC->UNICODE字符集的转换;假如没有设置则发生源代码字符集本地GBK->UNICODE的转换,’我’的编码是0x6211,’a’的编码是0x0061。 
4.         其它情况都不发生任何的字符集编码转换(源程序字符集和程序字符集一致),使用本地字符集GBK编码’,我’的编码是0xD2CE,’a’的编码是0x61。 
DEV-C++(gcc) 
1.         DEV-C++(gcc)编译器默认的程序字符集是UTF-8。 
2.         #pragma setlocale对编译没有影响。 
3.         如果字符字面量前有L(L”我”,L”a”),那么编译时将把字符字面量从配置字符编码GBK转换为UNICODE字符编码(L开头的字符字面量都是使用UNICODE字符编码),’我’的编码是0x6211,’a’的编码是0x0061。注:编译器参数为-finput-charset=GBK(指定源程序字符集为GBK,如果不指定编译器默认源程序字符集为UTF-8)。 
4.         其它情况会发生编译器配置参数GBK->UTF-8字符集的转换,’我’的编码是0x9E88E6,’a’的编码是0x61。这种情况下使用printf打印的时候会出现乱码,由于本地字符集是GBK,但实际字符编码是UTF-8,解决方法是在程序中把UTF-8转换为本地字符集GBK然后再调用printf打印。 
5.         在RH Linux系统下直接调用printf打印不会出问题,因为在该系统下默认字符集是UTF-8和编译器默认字符集一致,所以没有出现乱码问题。 
C-WindowsAPI层面 
VC8 
1.         如果编译参数配置了UNICODE则API被解释为调用UNICODE版本的API(带标记W的API,这里W代表UNICODE字符的含义)。 
2.         如果编译参数没有配置UNICODE则API被解释为调用单字符编码版本的API(带标记A的API)。 
VC6 
同VC8。 
DEV-C++(gcc) 
同VC8。 
D-杂项&总结 
1.         VC中UNICODE编译参数只控制windows API的展开,是UNICODE方式(W标记,这里W代表UNICODE字符的含义)还是单字符方式(A标记),其它不做控制。 
2.         C++中字符字面量前面如果有标识L,程序运行时这个字符字面量一定UNICODE字符编码方式的宽字符(不是其它字符编码方式)。 
3.         C++中如果字符字面量前面没有标识L,那么程序运行时这个字符字面量一定是编译器默认字符集编码方式(VC中是GBK字符集,’我’的编码是0xD2CE,’a’的编码是0x61,DEV-C++中是UTF-8, ’我’的编码是0x9E88E6,’a’的编码是0x61)。 
4.         C++中wchar_t,代表宽字符(UNICODE字符只是宽字符的一种),任何宽字符都可以赋值给wchar_t,包括UNICODE字符和其它宽字符(比如GBK编码的汉字字符),所以理论上wchar_t字符仅仅只代表是宽字符,不代表一定是UNICODE字符(不过一般情况下C++实现都使用UNICODE字符)。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics