Windows中C/C++字符串编码总结

字符/字符串编码

在C/C++中,字符串可以用一个以0结尾的ANSI单字节字符数组来表示。问题是,某些语言文字系统的字符集有非常多的符号。但这种方法一个字节只能表示256个符号,这是远远不够的。对于多余256个字符的字符集,有两种不同的解决方案:多字节和宽字符表示法。

注:ANSI即扩展的ASCII编码。不同的国家和地区制定了不同的标准,由此产生了 GB2312、GBK、GB18030、Big5、Shift_JIS等各自的编码标准。这些使用多个字节来代表一个字符的各种汉字延伸编码方式,称为 ANSI 编码。在简体中文Windows操作系统中,ANSI编码代表 GB2312编码;在繁体中文Windows操作系统中,ANSI编码代表Big5;在日文Windows操作系统中,ANSI 编码代表 JIS 编码。

Windows中,每个Unicode字符都使用UTF-16编码,UTF-16将每个字符编码为2个字节。默认情况下C编译器会把字符串中的字符转换成由8位char数据类型构成的一个数组:

//8位
char c  =  ‘A’;
char szBuffer[100]  =  “A String”;

Microsoft的C/C++编译器定义了一个内建的数据类型wchar_t,它表示一个16位的Unicode字符。

//16位
wchar_t c = L’A’;
wchar_t szBuffer[100]  =  L“A String”;

字符串之前的大写字母L通知编译器该字符串应当编译为一个Unicode字符串,当将此字符串放入程序的数据段时,会使用UTF16来编码每个字符。

Windows编码转换

Windows的内部完全用Unicode构建。也就是说,所有核心函数(创建窗口、显示文本、进行字符串处理等等)都需要Unicode字符串。调用函数时,如果向它传入一个ANSI字符串,那么函数首先会把字符串转换为Unicode,再把结果传给操作系统。为了这些字符串转换,系统会产生时间和内存上的开销。

如果一个函数参数需要字符串,则该函数通常有2个版本。例如:

CreateWindowExW
接收Unicode字符串,W代表Wide,宽字符。

CreateWindowExA
接收ANSI字符串,A即ANSI。

如果源模块时,定义了UNICODE宏,则调用CreateWindowExW,否则调用CreateWindowExA。在Visual Studio的项目属性中有一个字符集选项,就是决定是否定义UNICODE宏。

在C运行库中,有一系列函数处理ANSI字符和字符串,还有一系列处理UNICODE。与Windows不同的是,不会进行编码转换,它们是自力更生的。

Unicode与ANSI字符串转换可以使用MultiByteToWideChar和WideCharToMultiByte。

cout/wcout

std::cout  <<  “你好”;

这行代码可以输出一个字符串‘你好’到标准输出,默认为控制台。
在中文环境的Windows中,源码通常被默认保存为GBK编码,此处的字符串常量‘你好’以GBK编码被编译到目标文件的数据段。执行程序时,映射到内存中的同样为GBK编码,cout将‘你好’输出到控制台,控制台的默认编码也为GBK,于是显示出了‘你好’二字。

wcout.imbue(locale(""));
std::wcout  <<  L“你好”;

locale("")意思是获取环境中默认的locale,给wcout设置locale,让wcout知道需要将Unicode字符串转换为GBK,从而成功显示‘你好’。











参考文献—
《Windows核心编程》.Jeffrey Richter 著.黄陇;李虎 译

你可能感兴趣的:(c++,字符串,编译器,windows,c语言)