电脑发展的初期,只是在美国等英文国家使用,英文只有26个字母和其它字符,一个字节最多可以表示256个字符,如字母“A”用0x41(二进制01000001)表示,字母“a”用0x61(二进制01100001)表示。为了使各家电脑公司生产的电脑统一,美国搞了个国家标准ANSI,一直沿用至今,我们今天用的电脑普通情况下使用的都ANSI编码。

ANSI编码,每个字符占一个字节,但最多只能表示256个字符。
汉字等东亚语言字符怎么办呢?于是采用两个字节共同表示一个汉字的方法。二个字节理论上可以表示65535个字符。
因为ANSI标准是用一个字节的7个位表示一个普通字符,最高位为0(如字母“A”的二进制01000001),所以表示汉字就采用最高位为1来表示。如“中”字就是用0xD6、0xD0表示(二进制11010110、11010000)。
程序员判断一个字符是否为汉字,就是通过最高位是否为1来判断的。

但是,中国大陆的汉字表示方法叫GB码(中国国家标准,如GB2312),中国台湾、香港的汉字表示方法叫BIG5码(大五码,台湾一家民营公司提出),还有韩、日等字符,还是造成了计算机文字表示的不统一。
所以,在W98时代,电脑上网、收发邮件等经常出现乱码的现象(就是文字标准不统一造成的)

ANSI编码字符,叫多字节字符

UNICODE编码,每个字符占二个字节。也叫万国码(一种国际标准字符集,为世界上绝大多数已知的字符集定义了唯一的16位数值)

UNICODE编码的数字、字母等,保留原ANSI的8位编码,后面加上八个二进制0。
中国国家标准的UNICODE编码汉字,叫GB18030(与UNICODE相同,2002年开始执行),有27533个汉字。

UNICODE编码字符,叫宽字节字符

从Windows 2000开始,使用UNICODE编码,但为了保持兼容,默认的还是ANSI编码。

上面各位提出了两个函数:
WideCharToMultiByte()  //宽字符转多字节字符 
MultiByteToWideChar()  //多字节字符转宽字符 
就是用于两种字符转换的。

那么程序员如何处理这两种编码方式呢?

你可以使用默认的ANSI编码,也可以使用UNICODE编码
比如在VC60下,默认方式下建立的是ANSI编码的工程(注:编译的exe内部,其资源字符是以UNICODE保存)
建立UNICODE编码工程的方法:
1、为工程添加UNICODE和_UNICODE预处理选项。 
  具体步骤:打开[工程]->[设置…]对话框,在C/C++标签对话框的“预处理程序定义”中去除_MBCS,加上_UNICODE,UNICODE。(注意中间用逗号隔开)。
  在没有定义UNICODE和_UNICODE前,所有函数和类型都默认使用ANSI的版本;在定义了UNICODE和_UNICODE之后,所有的MFC类和Windows API都变成了宽字节版本了。
2、设置程序入口点
  因为MFC应用程序有针对Unicode专用的程序入口点,我们要设置entry point。否则就会出现连接错误。
  设置entry point的方法是:打开[工程]->[设置…]对话框,在Link页的Category:Output类别的Entry Point里填上wWinMainCRTStartup。

程序员的几个编程习惯:
1、用THCAR代替char
2、字符串加_T(""),如_T("你好")
3、用_tcscpy等代替strcpy等
ANSI操作函数以str开头,如strcpy(),strcat(),strlen();
Unicode操作函数以wcs开头,如wcscpy,wcscpy(),wcslen();
ANSI/Unicode互为兼容的操作函数以_tcs开头 _tcscpy(C运行期库);
ANSI/Unicode互为兼容的操作函数以lstr开头 lstrcpy(Windows函数);
考虑ANSI和Unicode的兼容,我们需要使用以_tcs开头或lstr开头的通用字符串操作函数。

这样,你在ANSI/UNICODE环境下编译时,可以不修改代码。

ANSI/UNICODE下的字符转换和其它
1、在ANSI下,如果程序本身产生的字符(串),如在代码中直接赋值的CString str = _T("你好"),不需要转换,但是,字符(串)是从其它地方来的,如读取UNICODE编码的文件,通信接收的UNICODE数据,则需要转换,转换使用上面两个函数。

2、同理,在UNICODE下,如果程序本身产生的字符(串),如在代码中直接赋值的CString str = _T("你好"),不需要转换,但是,字符(串)是从其它地方来的,如读取ANSI编码的文件,通信接收的ANSI数据,则需要转换,转换使用上面两个函数。

3、不管是ANSI,还是UNICODE,在资源中的字符串,如String Table中的、对话框的静态文本,都不需要转换,因为它们编译后是以UNICODE保存在.exe中的。
对话框上的汉字,只要是简繁同形的,同一个.exe运行在简体Windows和繁体Windows下都可以正常显示,当然两者必须要有对应的字体(库),都用System字体是可以的,或者简体Windows下用“宋体”,繁体Windows下用“新細明體”。简体的“中”和繁体的“中”字体相同,是简繁同形,简体的“国”和繁体的“國”字形不同,是简繁异形。

4、另外,同一个字符串在ANSI和UNICODE下计数个数不同。如“123你好”,在ANSI下是7个字符,在UNICODE下是5个字符。使用CString 的.GetLength()时要特别注意。

ANSI与UNICODE编码的体验 

1、你用Windows下的记事本新建立一个文件,输入一段文字,如“123abc你好”,你可以在任何时间双击打开它,可以看懂里面的文字。 
2、再打开该记事本,选“文件->另存为”,在对话框的“编码”中选“Unicode”,保存,你可以在任何时间双击打开它,可以看懂里面的文字。 

第1步建立的是ANSI编码文件,保存的汉字是GB2312/GBK汉字(ANSI编码),每个汉字占2个字节,数字字母是ANSI字符,每个字符占1个字节。 

第2步建立的是UNICODE编码文件,保存的汉字是GB18030汉字(UNICODE编码),每个汉字占2个字节,数字字母是UNICODE字符,每个字符占2个字节。

3、用十六进制编辑器,如UltraEdit,分别打开上面的两个文件,在十六进制下比较,你会发现其中的奥妙,还有,你再比较这两个文件所占的字节数(不等于字符数)。提示:UNICODE文本文件以0xFE、0xFF开头。

宽字符,Ansic和Unicode的更多相关文章

  1. [转帖]彻底弄懂UTF-8、Unicode、宽字符、locale

    彻底弄懂UTF-8.Unicode.宽字符.locale linux后端开发   已关注   彻底弄懂UTF-.Unicode.宽字符.locale unicode 是字符集 utf-8是编码格式.. ...

  2. 宽字符wchar_t和窄字符char——putwchar、wprintf

    宽字符wchar_t 与 窄字符char 先说下窄字符char,这个大部分读者应该很清楚,char类型的变量占一个字节(byte)(也就是8个bit(比特)),能表示256个字符,那char的范围有两 ...

  3. [c/c++] programming之路(25)、字符串(六)——memset,Unicode及宽字符,strset

    一.memset #include<stdio.h> #include<stdlib.h> #include<memory.h> void *mymemset(vo ...

  4. 宽字符、多字节、unicode、utf-8、gbk编码转化

    今天遇到一个编码的问题,困惑了我很长时间,所以就简要的的了解了一下常用的编码类型. 我们最常见的是assic编码,它是一种单字节编码,对多容纳256个字符. 我们在编程的时候经常遇到unicode,u ...

  5. 彻底弄懂UTF-8、Unicode、宽字符、locale

    目录 Unicode.UCS UTF8 宽字符类型wchar_t locale 为什么需要宽字符类型 多字节字符串和宽字符串相互转换 最近使用到了wchar_t类型,所以准备详细探究下,没想到水还挺深 ...

  6. 宽字符与Unicode (c语言 汉语字符串长度)

    在C语言中,我们使用char来定义字符,占用一个字节,最多只能表示128个字符,也就是ASCII码中的字符.计算机起源于美国,char 可以表示所有的英文字符,在以英语为母语的国家完全没有问题. 但是 ...

  7. 宽字符(UNICODE)字符集

    推荐使用宽字符(UNICODE)字符集,严格使用宽字符集的函数和定义.具体参考https://blog.csdn.net/qq_22642239/article/details/84822485

  8. 通过编写串口助手工具学习MFC过程——(三)Unicode字符集的宽字符和多字节字符转换

    通过编写串口助手工具学习MFC过程 因为以前也做过几次MFC的编程,每次都是项目完成时,MFC基本操作清楚了,但是过好长时间不再接触MFC的项目,再次做MFC的项目时,又要从头开始熟悉.这次通过做一个 ...

  9. SQL注入之Sqli-labs系列第三十二关(基于宽字符逃逸注入)

    开始挑战第三十二关(Bypass addslashes) 0x1查看源代码 (1)代码关键点 很明显,代码中利用正则匹配将 [ /,'," ]这些三个符号都过滤掉了 function che ...

随机推荐

  1. QFontMetrics的一个问题

    今天发现QFontMetric的一个问题 QFontMetrics可以输入一个字体和一个字符串,计算出字符串在这种字体下的显示尺寸. 这种计算比较耗时间,因此Qt内部应该是缓存了计算结果.具体方法是在 ...

  2. webclient 比浏览器加载页面慢的一个问题

    测试中发现webclient 比浏览器加载页面慢的一个问题:原因WebClient 支持 gzip, deflate,但是未设置 解决方案: class WebClientEx : WebClient ...

  3. linux下截取给定路径中的目录部分

    在日常运维中,有时会要求截取一个路径中的目录部分.截取目录的方法,有以下两种:1)dirname命令(最常用的方法):用于取给定路径的目录部分.很少直接在shell命令行中使用,一般把它用在shell ...

  4. Struts2动态方法调用(DMI)

    当structs.xml解析到Action的时候,默认执行的是此action的execute()方法,但是实际开发中,我们的action中含有很多方法,比如说增删改查的方法,那么structs.xml ...

  5. jQuery插件:跨浏览器复制jQuery-zclip

    jQuery-zclip是一个复制内容到剪贴板的jQuery插件,使用它我们不用考虑不同浏览器和浏览器版本之间的兼容问题.jQuery-zclip插件需要Flash的支持,使用时记得安装Adobe F ...

  6. Oracle字符分隔函数(split)

    为了让 PL/SQL 函数返回数据的多个行,必须通过返回一个 REF CURSOR 或一个数据集合来完成.REF CURSOR 的这种情况局限于可以从查询中选择的数据,而整个集合在可以返回前,必须进行 ...

  7. 创建pathing jar

    pathing jar是一个特殊的jar: 该jar文件只包含manifest.mf文件 该manifest文件只包含Class-Path,列出了所有需要真正加到classpath中的jar,或者di ...

  8. HDU2444-The Accomodation of Students-判断是否为二分图+ISAP

    要先判断是不是二分图.用黑白染色法. 遇到已经染过的跟当前的颜色相同时就说明不是二分图,也即出现了奇环 /*---------------------------------------------- ...

  9. cookie记住密码功能

    很多门户网站都提供了记住密码功能,虽然现在的浏览器都已经提供了相应的记住密码功能 效果就是你每次进入登录页面后就不需要再进行用户名和密码的输入: 记住密码功能基本都是使用cookie来进行实现的,因此 ...

  10. PHP 基础笔记

    数据类型 字符串 整数 浮点数 布尔值 数组 对象 NULL 未定义的变量,数据类型为 NULL. PHP 中数组和对象是不同的类型,而 js 中数组即为对象.(ps: es6 已经内置了 class ...