宽字符,Ansic和Unicode
电脑发展的初期,只是在美国等英文国家使用,英文只有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的更多相关文章
- [转帖]彻底弄懂UTF-8、Unicode、宽字符、locale
彻底弄懂UTF-8.Unicode.宽字符.locale linux后端开发 已关注 彻底弄懂UTF-.Unicode.宽字符.locale unicode 是字符集 utf-8是编码格式.. ...
- 宽字符wchar_t和窄字符char——putwchar、wprintf
宽字符wchar_t 与 窄字符char 先说下窄字符char,这个大部分读者应该很清楚,char类型的变量占一个字节(byte)(也就是8个bit(比特)),能表示256个字符,那char的范围有两 ...
- [c/c++] programming之路(25)、字符串(六)——memset,Unicode及宽字符,strset
一.memset #include<stdio.h> #include<stdlib.h> #include<memory.h> void *mymemset(vo ...
- 宽字符、多字节、unicode、utf-8、gbk编码转化
今天遇到一个编码的问题,困惑了我很长时间,所以就简要的的了解了一下常用的编码类型. 我们最常见的是assic编码,它是一种单字节编码,对多容纳256个字符. 我们在编程的时候经常遇到unicode,u ...
- 彻底弄懂UTF-8、Unicode、宽字符、locale
目录 Unicode.UCS UTF8 宽字符类型wchar_t locale 为什么需要宽字符类型 多字节字符串和宽字符串相互转换 最近使用到了wchar_t类型,所以准备详细探究下,没想到水还挺深 ...
- 宽字符与Unicode (c语言 汉语字符串长度)
在C语言中,我们使用char来定义字符,占用一个字节,最多只能表示128个字符,也就是ASCII码中的字符.计算机起源于美国,char 可以表示所有的英文字符,在以英语为母语的国家完全没有问题. 但是 ...
- 宽字符(UNICODE)字符集
推荐使用宽字符(UNICODE)字符集,严格使用宽字符集的函数和定义.具体参考https://blog.csdn.net/qq_22642239/article/details/84822485
- 通过编写串口助手工具学习MFC过程——(三)Unicode字符集的宽字符和多字节字符转换
通过编写串口助手工具学习MFC过程 因为以前也做过几次MFC的编程,每次都是项目完成时,MFC基本操作清楚了,但是过好长时间不再接触MFC的项目,再次做MFC的项目时,又要从头开始熟悉.这次通过做一个 ...
- SQL注入之Sqli-labs系列第三十二关(基于宽字符逃逸注入)
开始挑战第三十二关(Bypass addslashes) 0x1查看源代码 (1)代码关键点 很明显,代码中利用正则匹配将 [ /,'," ]这些三个符号都过滤掉了 function che ...
随机推荐
- IntelliJ Idea14 创建Maven多模块项目
Maven多模块项目的参考资料 Sonatype上的教程 http://books.sonatype.com/mvnex-book/reference/multimodule.html 在这个教程里, ...
- Linux shell文本过滤
正则表达式 --概念:一种用来描述文本模式的特殊语法 --由普通字符(例如:字符a到z),以及特殊字符(元字符,如/*?等)组成匹配的字符串 --文本过滤工具在某种模式之下,都支持正则表达式 --基本 ...
- JS多异步之间的协作方案
场景:使用工具函数downloadAllAsync接收一个URL数组并下载所有文件,结果返回一个存储了文件内容的数组,每个URL对应一个字符串. 好处:downloadAllAsync并不只有清理嵌套 ...
- iis7 运行 php5.5 的方法
首先添加IIS. 控制面板-〉程序-〉打开或关闭Windows功能 1. 勾选“Internet 信息服务” 2. 勾选“IIS 管理控制台” Internet 信息服务-〉Web 管理工具 ...
- 从 datetime2 数据类型到 datetime 数据类型的转换产生一个超出范围的值
具体的错误原因是:C#中的DateTime类型比SqlServer中的datetime范围大.SqlServer的datetime有效范围是1753年1月1日到9999年12月31日,如果超出这个范围 ...
- MVC架构设计——EF-Code First
详情参考:http://www.cnblogs.com/guomingfeng/archive/2013/05/28/mvc-ef-repository.html
- centos 7 安装mysql
# wget http://dev.mysql.com/get/mysql-community-release-el7-5.noarch.rpm # rpm -ivh mysql-community- ...
- Hibernate Synchronizer3——一个和hibernate Tool类似的小插件之使用方法
首先,要告诉大家的是,当我们要自动生成Mapping File的时候,我们除了使用hibernae tools之外,还可以通过一个更为简洁的插件,只需通过点击: 1.Hibernate Configu ...
- 70 sudo-用来以其他身份来执行命令
sudo命令用来以其他身份来执行命令,预设的身份为root.在/etc/sudoers中设置了可执行sudo指令的用户.若其未经授权的用户企图使用sudo,则会发出警告的邮件给管理员.用户使用sudo ...
- C#高级特性_Lambda
“Lambda 表达式”(lambda expression)是一个匿名函数 省略delegate,甚至省略参数类型: 直接用(参数)=> {语句或表达式} 例如: button1.Click ...