转自:http://blog.csdn.net/nodeathphoenix/article/details/7416725

1.    首先,说下窄字符char了,大家都很清楚,就是8bit表示的byte,长度固定。char字符只能表示ASII码表中的256个字符,包括前128个可见字符和后面的128个不可见字符。

wchar_t则是因为char所能表示的字符数太少(256个)而应运而生的,它的长度可以8bit,16bit,32bit,长度是与不同平台上的c库相关的。其实这个长度是根据指定平台上想要用的encoding编码方式来设定的。

在win32 MSVC环境下,c库中wchar_t的长度是2个byte,定义如下:
       typedef unsigned short wchar_t; /* 16 bits */
       它是按照utf-16编码,但是因为wchar_t定义的长度只有2个字节,所以它不能表示utf-16编码长度为4个字节的字符。即wchar_t只表示了utf-16的一个子集。换句话话说,就是MSVC下,wchar_t是utf-16编码的,但是只能表示utf-16的一个子集。按utf-16编码时,大部分字符都以固定长度的字节 (2字节) 储存.

在Linux-x86的GCC环境下,c库中wchar_t的长度为四个字节,用UCS-4(即utf-32编码方式)。

wchar_t就是存储的字符的unicode码值的编码值,如windows下就是unicode码值的utf-16编码值:
        TCHAR wide[] = L"态";
        在vs中watch为:  [0] 24577 L'态' wchar_t,即对应的十进制为24577,而"态"unicode表中查到的码值为十六进制的6001,而0x6001对应的十进制值就是24577.
        TCHAR wide[] = L"a"; 因为a的unicode值与ASCII值一样,为97. 如果unicode码值U小于0x10000,则U的UTF-16编码就是U对应的16位无符号整数。
        所以可知,0x6001的utf-16编码值就是0x6001。

 wchar_t   w1= L'中';  //Unicode 编码  ,宽字符字符串前面要加L
        wchar_t   w2= '中';   //Ansi编码

        printf( "%0x   %0x ",w1,w2);

结果:
        4e2d   d6d0
        虽然同样是赋值给wchar_t,但是不同的编码则值是不同的。同时也说明了wchar_t不光是可以存储Unicode宽字符,也可以存储其它的编码。但是如果是存储的Ansi编码,则按照宽字符的格式输出的是什么呢?

wchar_t c= L'中';
        wcout.imbue(locale("chs"));
        wcout<<c<<endl;
       上述代码能正常输出'中'字

wchar_t c= '中';
       wcout.imbue(locale("chs"));
       wcout<<c<<endl;
      上述代码不能正常输出'中'字,结果是什么也没输出。
      所以如果是需要宽字符参数的API里传入值为Ansi编码值的wchar_t可能会得到不可预测的结果。

c/c++标准只是声明wchar_t是一个可以表示字符集中的任意一个字符的足够宽的变量类型。wchar_t可以用任何encoding编码方式来存储这个字符,如ANSI, or UCS-2, or UCS- 4, 甚至是SCU-128,只不过我们通常是用unicode编码方式。wchar_t是与实现相关的。

所以为了可移植性,我们不能假定wchar_t的编码方式,然后根据编码方式做一些相关性操作,我们只能理解它为一个足够宽的字符类型。

参考:http://prog.eskosoft.com/2007/01/13/19

2.     ANSI码

ANSI码(American National Standards Institute),中文:美国国家标准学会的标准码。
      我们说的ansi码,指windows平台的一种ascii扩展码,他将ascii码扩展到8bits,增加了0x80-0xff共128个字符。
      对于ANSI码表而言,它兼容ASCII码表,0x00~0x7F之间的字符,依旧是1个字节代表1个字符。为使计算机支持更多语言,通常使用 0x80~0xFF 范围的 2 个字节来表示 1 个非英语字符。

像GB2312, BIG5, JIS 等使用ANSI码表的0x80~0xFF范围的 2 个字节来代表一个字符的各种汉字延伸编码方式,统称为ANSI 编码。比如:汉字 '中' 在GB2312码表中,使用 [0xD6,0xD0] 这两个字节存储。ANSI 编码与UTF-8一样,也是一种编码方式。

ANSI用一个字节来表示英语字符,用两个字节来表示一个非英语字符----这个字符位于某个字符集中的value。而字符集则可以是象GB2312,BIG5等在ASCII码表基础上扩展的字符集。这些字符集中兼容ASCII码表,并且加入了汉字(或繁体等)的字符集。

在vs 的c++环境下,可以通过如下方式查看汉字的ANSI编码值。char类型取值范围为-128~127。-42对应的char类型数据的原码为“10101010”,反码为"11010101",补码为"11010110",即十六进制为0xD6。同理-48则为0xD0.由此我们可知,ANSI,是通过两个窄字符char来表示一个汉字的。

当我们 在VS里输入一个“中”字时,其实它在GB2312里对应的两个字符值为0xD6和0xD0,那么VS里其实记录的就是[0xD6,0xD0]这个编码值。当我们电脑控制面板里设置的system locale为中文的时候,[0xD6,0xD0]在VS里就是呈现出“中”字;但是如果system locale设置为韩文时,[0xD6,0xD0]在VS里就是呈现出的就是它所表示的韩文字。即同一个ANSI编码值,对于不同的system locale值(不同的字符集),显示出来的字符是不一样的。

在VS工程属性里无论你选择Multi-Byte Character Set 或 Unicode Character Set字符集,char str[] = "中";这个表达式里,"中"都是ANSI编码,编码值都是[0xD6,0xD0]。即默认情况下,如果不加_T或L,默认情况下所有的字符都是ANSI编码。

3.   相互转换:

转换的时候是与encoding相关的,转换完后显示是和本地的language相关的。

windows:

MultiByteToWideChar和WideCharToMultiByte, MultiByteToWideChar可将utf-8编码的多字节或是ANSI编码的多字节(即两个字节)等转换为Unicode的宽字符wchar_t。例如,两个byte的窄字符表示的ANSI汉字转换为Unicode的宽字符wchar_t。WideCharToMultiByte可以将wchar_t转换utf-8或ANSI 等编码的多字节。

linux:mbstowcs和wcstombs

MultiByteToWideChar根据接口中指定的encoding方式将source多字符转换为对应的unicode值的宽字符WideCharToMultiByte则刚好相反,是根据指定的encoding编码方式将unicode字符转换为指定的编码方式的多字符。

char str[] = "中";
    int len=MultiByteToWideChar(CP_ACP,0,str, -1, NULL,0);
    wchar_t *w_string = new wchar_t[len];
    memset(w_string,0,sizeof(wchar_t)*len);
    MultiByteToWideChar(CP_ACP, 0, str,-1,w_string, len);

运行结果:

则len的长度为2,得到两个宽字符。*w_string则是'中'的宽字符值,*(w_string+1)则为结束符'\0'对应的宽字符值0.

详细的转换过程,下面的link中有详细描述:

http://www.ccw.com.cn/college/soft/b2c/os/htm2011/20111128_954237.shtml

另外附上一个非常不错的文章链接:

http://club.topsage.com/thread-2227977-1-1.html

宽字符wchar_t和窄字符char区别和相互转换相关推荐

  1. C++ 宽字符(wchar_t)与窄字符(char)的转换

    了解 长度 宽字符wchar_t的长度16位,可以用来显示中文等除英文外的其他文字, 窄字符    char   的长度  8 位,只能处理英文. 哪里可以见到 在VS2010, 2012, 2013 ...

  2. C++ 宽字符 窄字符 char wchar

    目录 wchar_t和char区别 宽字符 string和wstring的区别 wchar_t和char区别 参考链接 宽窄字符是与一个字符所占的字节数有关,如果一个字符只占一个字节,那么它就是窄字符 ...

  3. volatile,可变参数,memset,内联函数,宽字符窄字符,国际化,条件编译,预处理命令,define中##和#的区别,文件缓冲,位域

     1.volatile:要求参数修改每次都从内存中的读取.这种情况要比普通运行的变量需要的时间长. #include <stdio.h> #include <stdlib.h&g ...

  4. Windows核心思想-宽字符与窄字符(Unicode和ASCII)

    目录 基本概念 演示 基本概念 宽字符:Unicode字符,双字节 窄字符:ASCII字符,单字节 Windows中所有的底层函数都是Unicode编码 COM组件必须使用Unicode编码(COM组 ...

  5. C语言学习(十二)C语言中的字符(宽字符与窄字符)、从字符谈谈C语言的编码、转义字符

    C语言学习(十二)C语言中的字符(宽字符与窄字符).从字符谈谈C语言的编码.转义字符 目录 C语言学习(十二)C语言中的字符(宽字符与窄字符).从字符谈谈C语言的编码.转义字符 英文字符 字符的表示 ...

  6. C++ 宽、窄字符转换

    目录 locale setlocale函数 设置字符编码 单字符宽字符互相转换 mbstowcs函数 wcstombs函数 mbtowc函数 wctomb函数 宽.窄字符转换总结 查看本文前先弄清字符 ...

  7. wchar 格式控制符_控制台输出宽字符wchar_t的中文显示问题

    在缺省的C locale下,cout可以直接输出中文,但对于wcout却不行(至少VS 2005下不行).对于wcout,需要将其locale设为本地语言才能输出中文: wcout输出时显示不了中文, ...

  8. 字节字符区别Java_【JAVA基础】字符数组与字节数组的区别

    String.getBytes()和String.tocharArray(),字节数组和字符数组的区别 String.getBytes()是将字符串转化为一个字节数组.而String.toCharAr ...

  9. java字节流转字符串_字节流与字符流的区别及相互转换

    先来看一下流的概念: 在程序中所有的数据都是以流的方式进行传输或保存的,程序需要数据的时候要使用输入流读取数据,而当程序需要将一些数据保存起来的时候,就要使用输出流完成. 程序中的输入输出都是以流的形 ...

最新文章

  1. 扎克伯格又被黑,这次是他的 Pinterest 账号
  2. 有道python网课怎么样-如何用python“优雅的”调用有道翻译?
  3. c语言折半查找递归程序,C语言数据结构中二分查找递归非递归实现并分析
  4. Maven-学习笔记06【基础-Maven工程servlet实例】
  5. 电脑是否存在内存泄漏_STM32裸机内存管理解析
  6. Hadoop实战项目之网站数据点击流分析(转载分析)
  7. sklearn 下的 ensemble learning
  8. python语言之父丹尼斯里奇_C语言之父-丹尼斯里奇
  9. 转载一份anjuta教程
  10. zzulioj 1183: 平面点排序(一)(结构体专题)
  11. 8.Redis主从复制
  12. java异常捕获_java之异常捕获
  13. Sonatype Nexus3 搭建私有仓库
  14. ChatGPT爆火出圈,高质量文本标注数据成关键
  15. 高效遍历HashMap的方式,你知道的有几种呢
  16. ikbc机械键盘打字出现重复_机械键盘按键 按一次触发多次
  17. 台式计算机无法读取dvd,教你电脑读不了dvd光盘的修复教程
  18. Linux 下安装oci8扩展
  19. C++自学笔记v1.0:语法与编译过程
  20. android app trifit_Android人脸识别app——基于Face++,MVP+Retofit+RxJava+Dagger高度解耦

热门文章

  1. Windows统计分析进程流量工具AppNetworkCounter
  2. mysql.h函数解释_mysql时间格式化函数日期格式h和H区别
  3. VB程序设计教程(第四版)龚沛曾-实验8-7
  4. 局域网内提高网速的21个技巧
  5. eventfd的用法
  6. nowcoder_Bookshelf Filling_二分
  7. 【无标题】弘辽科技:怎么提高淘宝店铺访客量和流量?做好哪些方面?
  8. 使用 apifm-wxapi 开发微信小程序之商品砍价模块
  9. 《银河护卫队》系列终章IMAX中国首周末劲收3840万票房,全球斩获约2500万美元...
  10. 七牛云存储_入门及使用