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字符)。
操作系统 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字符)。
相关推荐
c/c++ 字符集转换[静态库,实例解析],libiconv
跨平台(windows Linux)是纯c实现 gbk/utf8互转,Ansi/Utf8互转,
各种 C++ 字符串类型转换(char *、wchar_t*、_bstr_t、CComBSTR、CString、basic_string 和 System.String) 本主题演示如何将各种 C++ 字符串类型转换为其他字符串。可以转换的字符串类型包括 char *、wchar_t*、_...
而由字符组成的集合则成为字符集,字符集由于包含字符的多少与异同而形成了各种不同的字符集。我们知道,所有字符在计算机中都是以二进制来存储的。那么一个字符究竟由多少个二进制位来表示呢?这就涉及到字符编码的...
在C/C++语言中没有专门的字符串变量,通常用字符数组来存放字符串。字符串是以“\0”作为结束符。
详解C++中十六进制字符串转数字(数值) 主要有两个方法,其实都是对现有函数的使用: 方法1: sscanf() 函数名: sscanf 功 能: 从字符串格式化输入 用 法: int sscanf(char *string, char *format[,...
4字符串转十六进制字符串、二进制字符串 5转义字符串 6随机数 源码包含了封装的功能模块类以及测试类, 全部源码都可以用VS2020编译通过,请放心使用! 友情提示,为了兼顾一些旧代码,预编译头文件用的是StdAfx.h...
通过调用封装API函数WideCharToMultiByte和MultiByteToWideChar,实现ANSI/UTF-8/Unicode编码格式的相互转换。有C++和C两个版本。
c++ 字符串逆序输出 用vs2005打开
字符串大小写转换的2种方法C++,对任意输入的字符串可实现字符串大小写的转换。
将输入的字符串解析为16进制输出
C++字符雨效果
C++全角半角字符转换
c++的des 加密解密代码,vs2017编译通过,可打开debug目录下的exe,查看效果,适合参考与学习
QT/C++二维码生成工具,通过手动输入字符串,生成二维码图片,支持本地保存和显示
C++字符数组练习题及解答[归类].pdf
c++ string 字符大小写的转换(csdn)————程序
C++的字符串匹配的应用文档。有代码和详细注释。主要取自王红梅的C++数据结构。加上自己的整理。
C++字符串处理系统
资料大全加程序 宽字符与多字符集(LPTSTR、LPCSTR、LPCTSTR、LPSTR) C++ 字符串之间的相互转化