说一说ASCLL和Unicode
关于字符编码这个展开来说有太多东西了,这里主要是想说一说最常说的ASCLL和Unicode字符编码的问题,这样至少你在用相关函数的时候,可以搞明白参数的真正含义。
ASCLL编码
计算机就是0和1的世界,所有的东西都是0和1演变而来,对字符来说,也是如此,每个字符在计算机内存中便是就是数字转换成的二进制0、1组合,这个数字就称为该字符的编码。
最常见的就是ACSLL编码了,整个码表对应如下:
ASCII值 | 控制字符 | ASCII值 | 控制字符 | ASCII值 | 控制字符 | ASCII值 | 控制字符 |
---|---|---|---|---|---|---|---|
0 | NUT | 32 | (space) | 64 | @ | 96 | 、 |
1 | SOH | 33 | ! | 65 | A | 97 | a |
2 | STX | 34 | " | 66 | B | 98 | b |
3 | ETX | 35 | # | 67 | C | 99 | c |
4 | EOT | 36 | $ | 68 | D | 100 | d |
5 | ENQ | 37 | % | 69 | E | 101 | e |
6 | ACK | 38 | & | 70 | F | 102 | f |
7 | BEL | 39 | , | 71 | G | 103 | g |
8 | BS | 40 | ( | 72 | H | 104 | h |
9 | HT | 41 | ) | 73 | I | 105 | i |
10 | LF | 42 | * | 74 | J | 106 | j |
11 | VT | 43 | + | 75 | K | 107 | k |
12 | FF | 44 | , | 76 | L | 108 | l |
13 | CR | 45 | - | 77 | M | 109 | m |
14 | SO | 46 | . | 78 | N | 110 | n |
15 | SI | 47 | / | 79 | O | 111 | o |
16 | DLE | 48 | 0 | 80 | P | 112 | p |
17 | DCI | 49 | 1 | 81 | Q | 113 | q |
18 | DC2 | 50 | 2 | 82 | R | 114 | r |
19 | DC3 | 51 | 3 | 83 | S | 115 | s |
20 | DC4 | 52 | 4 | 84 | T | 116 | t |
21 | NAK | 53 | 5 | 85 | U | 117 | u |
22 | SYN | 54 | 6 | 86 | V | 118 | v |
23 | TB | 55 | 7 | 87 | W | 119 | w |
24 | CAN | 56 | 8 | 88 | X | 120 | x |
25 | EM | 57 | 9 | 89 | Y | 121 | y |
26 | SUB | 58 | : | 90 | Z | 122 | z |
27 | ESC | 59 | ; | 91 | [ | 123 | { |
28 | FS | 60 | < | 92 | / | 124 | | |
29 | GS | 61 | = | 93 | ] | 125 | } |
30 | RS | 62 | > | 94 | ^ | 126 | ` |
31 | US | 63 | ? | 95 | _ | 127 | DEL |
可以看到0-127对应的英文中0-9,a-z,A-Z及控制字符(如换行字符\n等),这些是最基本的英文表达,有了他们我们基本上可以组合出所有的英文表达了。
扩展ASCLL编码
但是这是远远不够的,一些其他欧美国家语言(如德文、法文)有多音字符,还有尽管在最开始ASCLL编码出现的时候还是命令行,但是人们还是想在这上面加些其他的玩意儿,这就有了如下的扩展ACSLL码表了:
可以看到128-255都是一些德文、法文多音字符(上面带点的字符...)和一些希腊符号及其他的符号。
但是注意ACSLL只有0-127字符是标准定义的,扩展ACSLL(128-255)编码表示的字符都是OEM厂商自己定义的,最常用的是IBM的。
再扩展ASCLL
但是这样的扩展在遇到中东文字尤其是东亚如中国的文字后又不行了,那么多汉字,如何用最开始的char(8 bit)编码来表示呢?
如下程序:
- #include <stdio.h>
- int main()
- {
- char a1[] = "a";
- char b1[] = "b";
- char c1[] = "c";
- char a2[] = "我";
- char b2[] = "你";
- char c2[] = "他";
- printf("a1:%d——b1:%d——c1:%d\n", a1[0],b1[0],c1[0]);
- printf("a2:%x——b2:%x——c2:%x\n", a2[0],b2[0],c2[0]);
- printf("a2:%x——b2:%x——c2:%x\n", a2[1],b2[1],c2[1]);
- return 0;
- }
查看内存:
命令行输出结果为:
- a1:97——b1:98——c1:99
- a2:ffffffce——b2:ffffffc4——c2:ffffffcb
- a2:ffffffd2——b2:ffffffe3——c2:fffffffb
哈哈,看到了吧,英文a、b、c在内存是一个字节,但是中文你、我、他在内存中就是两个字节了。
我们可以直接使用printf打印字符,但是一次只能打印一个字节,中文要如上一样分两次打印。
那么中文是如何编码的呢,我们知道传统的ASCLL一个字节最多也只能表示2^8=256个字符,这对于中文是远远不够的,那么就如上所说,中文编码在传统的ASCLL扩展编码的基础上将在第一个字节值是128-255时,在每个字节后附加一个字节,这样就可以表示的字符数为128*256=32768个,一般称为ANSI编码,这对于一般中文表达来说是够了的。
如上的我、你、他编码分别如下(注意低位在前):
我:0xd2ce
你:0xe3c4
他:0xfbcb
代码页
但是这对于一般的表达是够的,问题是中文还有繁体字,还有东亚其他国家的文字如韩国、日本以及中亚等象形字国家的文字,这么多文字也不是32768个编码能够全部表达的。怎么办呢?
针对不同国家不同地区,把常用字符组合成一个ASCLL扩展表并将它们编号,每一个编号表示的扩展表称为一个代码页,现在常见的代码页都有自己的名称,如936代码页就是我们常用的GBK编码,如
950 繁体中文
949 朝鲜语
936 简体中文
932 日语
都是各个国家和地区的代码页。
注意相同的编号在不同的代码页下表示的是不同的字符,
如0xd2ce在中文代码页936对应中文字符我,但是在日语代码页下就不是了。如果代码页设置不正确,很可能显示为乱码,下面我就会演示这一情况。
Unicode编码
上面我们看到了,不同的代码页整的太麻烦了,能不能有一种统一的编码方式来完成编码和字符对应呢?
Unicode就是干这个的。
不同于上面说的同一ANSI编码在不同的代码页下表示不同的字符,同一Unicode编码在任何时候都表示唯一的字符,这你就要问了这得多少个字节才能表示世界上所有的字符啊,哈哈,最简单的就是UTF32编码了,4个字节表示一个字符,总共2^32=4294967296,这下总算够用了。
但是问题是,对于网络传送等场合这样同一个字符要占4个字节,带宽内存什么的浪费了,人们就想到了各式各样的压缩算法:常用的UTF16一般使用两个字节表示常用字符,对于不能表示的或不常用的字符才使用32位编码,这是Windows程序默认的Unicode编码方式;UTF8编码更过分,按照不同的国家文字的多少分别使用1个字节、2个字节、3个字节和4个字节表示,常用于网络传速。
对于如下程序:
- #include <Windows.h>
- #include <stdio.h>
- #include <locale.h>
- int main()
- {
- wchar_t a1[] = L"a";
- wchar_t b1[] = L"b";
- wchar_t c1[] = L"c";
- wchar_t a2[] = L"我";
- wchar_t b2[] = L"你";
- wchar_t c2[] = L"他";
- wprintf_s(L"a1:%x——b1:%x——c1:%x\n", a1[0], b1[0], c1[0]);
- wprintf_s(L"我:%x——你:%x——他:%x\n", a2[0], b2[0], c2[0]);
- _locale_t lt = _get_current_locale();
- printf_s("\n之前代码页:%s\n", (lt->locinfo)->lc_category[0].locale);
- _wsetlocale(LC_ALL, L"chs");
- lt = _get_current_locale();
- wprintf_s(L"现在代码页:%s\n", (lt->locinfo)->lc_category[0].wlocale);
- wprintf_s(L"\na1:%x——b1:%x——c1:%x\n", a1[0], b1[0], c1[0]);
- wprintf_s(L"我:%x——你:%x——他:%x\n", a2[0], b2[0], c2[0]);
- return 0;
- }
查看内存:
程序运行结果为:
- a1:61
- 之前代码页:(null)
- 现在代码页:Chinese (Simplified)_People's Republic of China.936
- a1:61——b1:62——c1:63
- 我:6211——你:4f60——他:4ed6
现在看到了乱码现象吧?第一次输出a1,b1,c1,a2,b2,c2时只能输出一部分,转换不正确出不来。
这是因为控制台程序显示只能使用ANSI方式,可以右键查看属性,如下:
即显示默认的是使用简体中文代码页936,即GBK编码。
我们在内存中的字符编码是Unicode方式,要显示到GBK编码的控制台窗口上,必须经过编码转换,那么编码转换依据什么呢,就是依靠当前的代码页来完成转换的。
如对于字符"我"的转换过程:
Unicode编码:0x6211->对应字符:"我"->查询代码页936->ANSI编码:0xd2ce
反之亦然。
最开始没有正确设置转换用的代码页,所以转换不正确,也就不能正确显示,设置转换用的代码页后就可以正常显示了。
在windows中的编码转换函数MultiByteToWideChar和WideCharToMultiByte的第一个参数都是codepage,即设定用于编码转换的表(代码页)。
现在你应该明白为什么很多时候和场合要设置locale了吧,设置不同的locale就是对应不同的代码页,这样显示转换才能成功,对应的常见场合有网页显示和数据库数据读取。
那关于编码的问题就这么多了,弄懂整个编码演变历史和过程,我们使用相关函数的时候就没有什么大问题了。
演示源代码下载链接
原创,转载请注明来自http://blog.csdn.net/wenzhou1219
说一说ASCLL和Unicode的更多相关文章
- ASCLL、Unicode和UTF-8编码的理解
我们已经讲过了,字符串也是一种数据类型,但是,字符串比较特殊的是还有一个编码问题. 因为计算机只能处理数字,如果要处理文本,就必须先把文本转换为数字才能处理.最早的计算机在设计时采用8个比特(bit) ...
- Python学习:基本概念
Python学习:基本概念 一,python的特点: 1,python应用场景多;爬虫,网站,数据挖掘,可视化演示. 2,python运行速度慢,但如果CPU够强,这差距并不明显. 3,严格的缩进式编 ...
- python注释方法以及编码问题
一.单行注释 在python中常使用"#"来进行单行注释,其快捷键为"ctrl+/",如果要对多行代码也就是代码块进行注释时,也可以选中多行按下 "c ...
- HTML基础学习笔记(2)
HTML学习笔记(2) 1 head标签中的结构 编码结构:<meta charset="UTF-8"> charset---编码 ascll ansi Unicode ...
- html基础标签下
1.1 单标签 ◆注释标签 ctrl+/ ◆水平线标签 <hr> ◆换行标签 <br> 1.2 双标签 ◆段落标签 <p></p> ◆ ...
- 2017年5月24日 HTML 基础知识(二)
1 快捷方式:html:xt +tab 过渡XHTML html:xs+tab 严格XHTML !+tab html5的标签结构 2.Charset 编码 <meta charset ...
- 老齐python-基础2(字符串)
1.字符串 1.1索引和切片 索引: >>> lang = "study python" >>> lang[0] 's' >>> ...
- Microsoft SQL Server Transact-SQL
Microsoft SQL Server Transact-SQL 1.SQL 1.1数据定义语言(DDL) create 创建数据库或数据库对象:alter 修改数据库或数据库对象:drop 删除数 ...
- python中文编码 - python基础入门(5)
python到目前为止,一共有两个版本,分别是2.x和3.x版本,根据官方正式通知2020年停止对python更新和维护,距离今天还有110天左右,所以正在学习python的小伙伴应该暗中庆幸一波. ...
随机推荐
- C++ 用宏实现swap(a,b)
#include <iostream> using namespace std; #define SWAP(a,b) a^=b,b^=a,a^=b int main(void){ int ...
- 常用Linux命令记录
[RSYNC] 指定SSH端口从远程服务器同步文件至本地目录 rsync -avH --progress '-e ssh -p 3600' user@remote_ip:remote_dir loc ...
- BI领导驾驶舱的功能特点
随着企业的信息化能力越来越强,商业智能(BI)对他们而言已不仅仅是数据展现的工具.商业智能必须能够与企业的业务流程相联系,做企业随需随用的“战略军师”.“BI领导驾驶舱”的出现无疑顺应了BI的发展趋势 ...
- 2016.10.29 NOIP模拟赛 PM 考试整理
300分的题,只得了第三题的100分. 题目+数据:链接:http://pan.baidu.com/s/1o7P4YXs 密码:4how T1:这道题目存在着诸多的问题: 1.开始的序列是无法消除的( ...
- [No000072]Windows环境变量列表
环境变量是目录的可以直接在绝对路径中引用,所有值均可在CMD下用 echo 命令显示以查看. 最常用的有—— %APPDATA% %HOMEPATH% %ProgramFiles% %SYSTEMRO ...
- Eclipse: 提示 Toolchain "MinGW GCC" is not detected
解决办法: 1. 把 D:\MinGW\bin, 设置到 PATH 路径. 2. 重启 eclipse
- http协议进阶(三)补充:报文首部
之前写的关于报文首部的传送门: 报文首部:http://www.cnblogs.com/imyalost/p/5708445.html 通用首部字段:http://www.cnblogs.com/im ...
- keyset获取元素
public static void main(String[] args){ Map map = new HashMap(); map.put("apple", "新鲜 ...
- javascript马赛克遮罩图片切换效果:XMosaic.js(转)
新鲜出炉的javascript图片切换特效,实现的是马赛克遮罩切换.在flash里,好实现遮罩动画很简单,不过JS实现起来就有些困难了. XMosaic.js,与XScroll.js和XScroll2 ...
- 备忘:aliyun maven mirror
<mirror> <id>alimaven</id> <name>aliyun maven</name> &l ...