ascii编码与unicode编码

ascii编码与unicode编码

01

ascii编码

定义字符数组 szHello ,初值为 "Hello"。编写程序1:

#include<stdio.h>#include<string.h>#include<stdlib.h>int main(int argc, char* argv[]){  char szHello[] = "Hello";  printf("%s\r\n", szHello);  system("pause");  return 0;}

按 F10 进行单步调试,发现 Hello 字符串的每个字符在内存中各占一个字节,这就是 ascii码 。由美国人发明,所以只出现大小写英文字母、数字和一些符号。因此,最早只有127个字符被编码到计算机里,也就是 7位 2进制数字,最高位(第八位)为 0 。

这个编码表被称为 ascii编码,比如大写字母 H 的编码是 72(16进制48),小写字母 o 的编码是 111(16进制6F)。

02

unicode编码

定义字符数组 szHello ,初值为 "Hello同学们"。编写程序2:

#include<stdio.h>#include<string.h>#include<stdlib.h>int main(int argc, char* argv[]){  char szHello[] = "Hello同学们";  printf("%s\r\n", szHello);  system("pause");  return 0;}

按 F10 进行单步调试,发现字符串 "Hello" 的每个字符在内存中仍各占一个字节,但是字符串 "同学们",每一个汉子在内存中却占两个字节。

这是因为,在中国1990年出版的《辞海》就高达14872个汉字,上面提到的 ascii编码,每个字只用一个字节表示,最多可表示 256 个字,显然是远远不够的,至少需要两个字节,而且还不能和ASCII编码冲突,所以,中国制定了GB2312编码,用来把中文编进去。

可以想得到的是,全世界有上百种语言,日本,韩国等,并且各国有各国的标准,就会不可避免地出现冲突,结果就是,在多语言混合的文本中,显示出来会有乱码。

因此,unicode编码应运而生。unicode编码在内存中占两个字节,最多可表示 65535 个字,可以把所有语言都统一到一套编码里,这样就解决了乱码问题。

通过调试结果也可以看出,字节值为正数,用 ascii 编码表示英文;字节值负数,用 unicode 编码表示中文。

编译执行,并不会出现乱码输出。

03

程序使用unicode编码

但是如果在英文中文混用的情况下,编译器判断一个字节出错时,会连续判断错误,造成大面积的乱码。例如将 6F 改为 8F,如下图所示,导致"同学们"字符串均发生乱码。

因为中英文混用时,内存中一会占一个字节,一会占两个字节,编译器处理的难度会提升很多,容易造成乱码现象。利用空间换时间的思维,不论英文还是中文,都利用 unicode编码方式,全部在内存空间中占两个字节。

将内存空间占一个字节的变量类型 char ,改为内存空间占两个字节的变量类型 unsigned short int 。编写程序3:

#include<stdio.h>#include<string.h>#include<stdlib.h>int main(int argc, char* argv[]){  unsigned short int szHello[] = "Hello同学们";  printf("%s\r\n", szHello);  system("pause");  return 0;}

因为字符串 "Hello同学们" 仍是 ascii编码方式,所以编译未通过,提示无法从 char [12] 转换为 unsigned short [],没有可以进行这种转换的环境。

在字符串前加 L ,如 L"我的字符串" 表示将 ascii编码字符串转换成 unicode编码的字符串。在字符串 "Hello同学们" 前加 L,编写程序4:

#include<stdio.h>#include<string.h>#include<stdlib.h>int main(int argc, char* argv[]){  unsigned short int szHello[] = L"Hello同学们";  printf("%s\r\n", szHello);  system("pause");  return 0;}

编译通过。按 F10 进行单步调试,字符串中的每个字符和汉字都各占两个字节的内存空间。

printf 函数是按 ascii编码方式打印,默认字符串 \0 结尾,因为字符串 "Hello同学们" 是 unicode编码,所以在 H 字符后是 00 ,printf 看见 00 结束打印,只输出 H 。

查看 MSDN 可知,打印 unicode编码字符串,必须要用 wprintf 函数。因为 wprintf函数是 printf函数的宽字节版本,但两函数的行为相同。

将 printf 函数改为 wprintf 函数。编写程序5:

#include<stdio.h>#include<string.h>#include<stdlib.h>int main(int argc, char* argv[]){  unsigned short int szHello[] = L"Hello同学们";  wprintf(L"%s", szHello);  system("pause");  return 0;}

编译执行,只输出了 Hello,而中文部分字符串"同学们"却没有输出。

只有利用 setlocale 函数,设置当前位置,才能显示中文部分的字符串。查看 MSDN,输出简体中文用 "chs" 。

根据 MSDN 获取到的修改方式,编写程序6:

#include<stdio.h>#include<string.h>#include<stdlib.h>#include <locale.h>int main(int argc, char* argv[]){  setlocale(LC_ALL, "chs");  unsigned short int szHello[] = L"Hello同学们";  wprintf(L"%s\r\n", szHello);  system("pause");  return 0;}

编译执行,输出 "Hello同学们" 成功。

04

可选择使用ascii编码或unicode编码

利用编译选项宏实现 ascii编码方式和unicode编码方式的随时切换,思路为如果定义宏 MYUNICODE ,代码全部为 unicode编码模式,否则代码全部为 ascii编码模式。编写程序7:

#include<stdio.h>#include<string.h>#include<stdlib.h>#include <locale.h>#define MYUNICODE#ifdef MYUNICODE#define TCHAR        unsigned short int#define _tprintf     wprintf#define _tmain       wmain#define _tsetlocale  _wsetlocale#define _tsystem     _wsystem#define _T(x) L ## x        #else #define TCHAR     char #define _tprintf     printf#define _tmain       main#define _tsetlocale  setlocale#define _tsystem     system#define _T(x) x   #endifint main(int argc, char* argv[]){  _tsetlocale(LC_ALL, _T("chs"));  TCHAR szHello[] = _T("Hello同学们");  _tprintf(_T("%s\r\n"), szHello);  _tsystem(_T("pause"));  return 0;}

按 F10 进行单步调试,字符串以 unicode编码方式在内存中存储。

注释掉宏 MYUNICODE 。编写程序8:

#include<stdio.h>#include<string.h>#include<stdlib.h>#include <locale.h>// #define MYUNICODE#ifdef MYUNICODE#define TCHAR        unsigned short int#define _tprintf     wprintf#define _tmain       wmain#define _tsetlocale  _wsetlocale#define _tsystem     _wsystem#define _T(x) L ## x        #else #define TCHAR     char #define _tprintf     printf#define _tmain       main#define _tsetlocale  setlocale#define _tsystem     system#define _T(x) x   #endifint main(int argc, char* argv[]){  _tsetlocale(LC_ALL, _T("chs"));  TCHAR szHello[] = _T("Hello同学们");  _tprintf(_T("%s\r\n"), szHello);  _tsystem(_T("pause"));  return 0;}

按 F10 进行单步调试,字符串以 ascii编码方式在内存中存储。

(0)

相关推荐