VC工程中的字符集工程属性和字符编码(转)

一工程字符集属性

工程属性里,字符集可以选择“Use Unicode Character Set”和“Use Multi-Byte Character Set”。此选项只控制代码里的API是用宽字符版的还是ANSI字符版的,它控制不了代码里的字符是用Unicode编码还是ANSI编码。

如果选择了“Use Unicode Character Set”,则代码里用到的API被解释为UNICODE版本的API(带标记W的API),如MessageBox被解释为MessageBoxW;
如果选择了“Use Multi-Byte Character Set”,则代码里用到的API被解释为ANSI编码版本的API(带标记A的API),如MessageBox被解释为MessageBoxA。 

二字符编码

假设当前操作系统的字符集为GBK,则:

1 源代码文件里面的字符集

     使用当前操作系统的字符集GBK保存源程序,如“中”字的编码值为[0xD6,0xD0]。则在源程序的cpp文件中“中”字就是编码值[0xD6,0xD0]的形式保存。 

2  运行时字符串变量的字符集

字符变量的字符编码是由操作系统的字符集和前缀L来决定的:

1> 如果字符串常量前面如果有标识L,则无论系统的字符集是什么,被此字符串赋值的变量的内容都是Unicode编码的。编译器会将在cpp文件中以GBK编码保存的“中”字对应的UNICODE编码的值0x4E2D赋值给字符串变量。

2> 如果字符串常量前面没有标识L,那么被此字符串赋值的变量的内容是编译器默认字符集编码方式(VC编译器默认的字符集是操作系统的字符集,此例为GBK)。 

比如简单的说,字符(串)在程序文件(可执行文件,非源文件)中的表示,与在程序执行中在内存中的表示一致。考虑两种情况:
A、char c = 0x61;
B、char c = 'a';
情况A下,编译器可以直接认识作为整数的c,但是在情况B下,编译器必须将'a'翻译成整数。编译器的策略也很简单,就是直接读取字符(串)在源文件中的编码数值。比如:
const char* s = "中文abc";
这段字符串在GB2312(Windows 936),也就是我们的windows默认中文系统源文件中的编码为:
0xD6 

  0xD0   0xCE 0xC4 0x61 0x62 0x63
在UTF-8,也就是Linux默认系统源文件中的编码为:
0xE4   0xB8   0xAD   0xE6   0x96   0x87   0x61   0x62   0x63
一般情况下,编译器会忠实于源文件的编码为s赋值,例外的情况比如VC会自作聪明的把大部分其他类型编码的字符串转换成GB2312(除了像UTF-8 without signature这样的幸存者)。
程序在执行的时候,s也就保持是这样的编码,不会再做其他的转换。

宽字符 wchar_t
正如char没有规定大小,wchar_t同样没有标准限定,标准只是要求一个wchar_t可以表示任何系统所能认识的字符,在win32 中,wchar_t为16位;Linux中是32位。wchar_t同样没有规定编码,因为Unicode的概念我们后面才解释,所以这里只是提一下,在 win32中,wchar_t的编码是UCS-2BE;而Linux中是UTF-32BE(等价于UCS-4BE),不过简单的说,在16位以内,一个字 符的这3种编码值是一样的。因此:
const wchar_t* ws = L"中文abc";
的编码分别为:
0x4E2D   0x6587    0x0061   0x0062   0x0063                                                //win32,16位
0x00004E2D   0x00006587    0x00000061   0x00000062   0x00000063        //Linux,32位
大写的L是告诉编译器:这是宽字符串。所以,这时候是需要编译器根据locale来进行翻译的。
比如,在Windows环境中,编译器的翻译策略是GB2312到UCS-2BE;Linux环境中的策略是UTF-8到UTF-32BE。
这时候就要求源文件的编码与编译器的本地化策略集中代码翻译的策略一致,例如VC只能读取GB2312的源代码(这里还是例外,VC太自作聪明了 ,会将很多其他代码在编译时自动转换成GB2312),而gcc只能读取UTF-8的源代码(这里就有个尴尬,MinGW运行win32下,所以只有 GB2312系统才认;而MinGW却用gcc编写,所以自己只认UTF-8,所以结果就是,MinGW的宽字符被废掉了)。
宽字符(串)由编译器翻译,还是被硬编码进程序文件中。
 
原文地址:https://www.cnblogs.com/touhoujerry/p/4807832.html