学习C语言的时候您应该接触过ASCII码。学习本章的内容需要ASCII知识。

学习Unicode有必要了解字符集的历史。从最早的象形字开始,我们使用字符文字已经有近6000年了。19世纪的几个发明家发明了电报,当时在电报中使用的代码是Morse代码。字母表中的每个字符对应于一系列短和长的脉冲。

计算机是处理的数据其实是一系列1和0。每一段数字都代表一种字符。这就是ASCII码。7位数的ASCII码对于美国的字符集支持得很好。不幸的是地球上有一百多个国家和地区,2000多个民族。对于美国以外的用户来讲在计算机中显示自己国家的文字困难重重。

尤其是中国,日本,朝鲜更是如此。以中国为例,有数也数不清的汉字。办法总是有的。人们引入了"代码页"和"双字节字符集"的概念。这种编码方式非常庞大和复杂,不利于维护。这个时候Unicode应运而生了。

Unicode的解决方案非常简单。既然不能用7位或者8位数值表示,那么我们应该试一下更宽的值。例如16位,这样就允许表示65536个字符。Unicode和ASCII是兼容的。也就是说,前128个字符的数值是相同的。

Unicode的最大好处是只有一个字符集。当然Unicode也有缺点,Unicode占用的内存是ASCII码的两倍。而且人们还不太习惯Unicode。

对于程序员来讲,8位的ASCII码和16位的Unicode是我们必须面对的问题。为了解决宽字符(16位)问题,Windows在头文件中定义了"新"数据类型。

typedef unsigned short wchar_t;

可以看出wchar_t其实是16位的无符号短整型数。Windows用这种方法存贮16位字符。

wchar_t *p = L"Hello!";

在"Hello!"前有一个大写字母L(代表long)。这将告诉编译器该字符串按宽字符保存。即每个字符占用2个字符。存贮该字符串需要14个字节。字符串末尾还有一个/0也需要2个字节。

我们都知道如何获得字符串的长度。

int iLength;
char *pc = "Hello!";
iLength = strlen(pc);

函数strlen()返回字符串的长度,长度将不包括末尾的/0。变量iLength将等于6,也就是字符串中的字符数。

接下来我们试着用strlen()检查宽字符的字符串。

wchar_t *pw = L"Hello!";
iLength = strlen(pw);

strlen()的参数应该是char类型的指针,但是现在却接受了一个unsigned short类型的指针。编译后您会发现iLength等于1。

why?字符串"Hello!"中的6个字符宽字符代码如下:

0x0048 0x0065 0x006c 0x006c 0x006f 0x0021

Intel处理器在内存中将其存为:

48 00 65 00 6c 00 6c 00 6f 00 21 00

strlen()的工作过程是遇到0就结束。因为0表示一个字符串的结束。当读完"48"后strlen()遇到的是0,所以strlen()返回1。

由上例可以看出C语言的函数无法正确处理宽字符。在参数中有字符串的函数全部需要重写。strlen()的宽字符版本是wcslen(),并且在STRING.H中和WCHAR.H中均有声明.

现在我们知道,要得到宽字符串的长度,可以调用

iLength = wcslen(pw);

该函数返回将返回字符串中的字符数6。请记住,改成宽字节后字符串的字符长度不变,只是字节长度改变了。千万不要混淆。

因为Unicode占用两倍的存储空间,所以宽字节运行库中的函数比常规的函数大。所以最好是建立两个版本的程序,一个处理ASCII字符串,另一个处理Unicode字符串。但是这样以来又引来了另一个小问题。因为每一个实现特定功能的函数都有两个版本,所以名字不好记。不管是ASCII版本还是Unicode版本,都用相同的名字该多好啊?幸好这个问题已经得到了解决。

解决办法是使用Visual C++包含的TCHAR.H头文件。该头文件不是标准C的一部分。为了与标准C的头文件分别开来,该头文件内定义的每个函数和宏定义的前面都有一条下划线。

TCHAR.H为需要字符串的标准运行库函数提供了一系列的替代名称。有时这些名称被称为"通用"函数名,因为它们既可以指向函数的Unicode版本,也可以指向ASCII版本。
以_tcslen()为例如果定义了_UNICODE的标识符,并且程序中包含了TCHAR.H,那么_tcslen()就定义为wcslen():

#define _tcslen wcslen

如果没有定义_UNICODE,则_tcslen()被定义为strlen()。

#define _tcslen strlen

TCHAR.H还用一个新的数据类型TCHAR来解决两种字符数据类型的问题。如果定义了_UNICODE标识符,那么TCHAR就是wchar_t:

typedef wchar_t TCHAR;

否则TCHAR就是char:

typedef char TCHAR;

还记得第一章里出现过的TEXT()吗?那是为了兼容UNICODE字符集所做的改动。下面就来看看TEXT()在头文件中是怎么定义的。

#define __T(x)    L##x

后面的L##x您可能看不懂。很少有书提到它。但那确实是标准C预处理的一部分。这一对"##"称为粘贴号(token paste)。看来我们对标准C的了解还不够。是时候买本"The C Programming Language"了。它将字母L添加到宏参数上。

__T("Hello!") 等于 L##"Hello!" 等于 L"Hello!"。

此外还有两个宏与__T定义相同:

#define _T(x) __T(x)
#define _TEXT(x) __T(x)

WINNT.H头文件中还定义了一个宏,该宏也跟__T一样,将L添加到字符串前。

#ifdef UNICODE
#define __TEXT(quote) L##quote
#else
#define __TEXT(quote) quote
#endif

#define TEXT(quote) __TEXT(quote)

转载:http://www.cnblogs.com/Jessy/articles/1746337.html

转载于:https://www.cnblogs.com/qhyuan1992/p/5385336.html

VC中的Unicode相关推荐

  1. VC中使用Unicode的一些列问题

    VC6.0中默认的是多字节编码,而自从VS2005以后都是默认的Unicode字符编码格式了.至于ANSI, MBCS(多字节编码)和UNICODE之间的区别可以百度一下.下面的一篇博文写的也比较详细 ...

  2. VC中的宏 (#define) 与预处理 (#if/#ifdef/#pragma) 的使用方法总结。

    C/C++ 预定义宏 例子:C/C++ 预定义宏的取值 C/C++ 预定义宏用途:诊断与调试输出 CRT 的诊断与调试输出:assert, _ASSERT/_ASSERTE, _RPTn/_RPTFn ...

  3. VC中的一些字符类型及其转换

    一.VC中字符串类型的互相转换       总是觉得VC中的类型纷繁复杂,扑朔迷离.因为有了Unicode,因为C.C++类型相互转化如此不同.保存char的不止char一种,还可以用short,un ...

  4. VC++中操作XML(MFC、SDK)

    VC++中操作XML(MFC.SDK) XML在Win32程序方面应该没有在Web方面应用得多,很多Win32程序也只是用XML来存存配置信息而已,而且没有足够的好处的话还不如用ini.VC++里操作 ...

  5. 浅谈Python和VC中的编码问题(转)

    以前编码问题总能让自己凑或蒙过去,最近要做一个项目服务器端用python写,客户端用c++,工程编译的字符集使用UNICODE.之间通过socket进行通信,通信过程中编码转换问题把我搞得晕头转向,逼 ...

  6. VC中GetLastError()获取错误信息的使用,以及错误代码的含义

    在VC中编写应用程序时,经常需要涉及到错误处理问题.许多函数调用只用TRUE和FALSE来表明函数的运行结果.一旦出现错误,MSDN中往往会指出请用GetLastError()函数来获得错误原因 可问 ...

  7. VC++中的char,wchar_t,TCHAR(转载)

    VC++中的char,wchar_t,TCHAR 大家一起做一个项目,经常发现有的人爱用strcpy等标准ANSI函数,有的人爱用_tXXXX函数,这个问题曾经搞的很混乱.为了统一,有必要把来龙去脉搞 ...

  8. VC中数字与字符串转换方法

    VC中数字与字符串转换方法 u     字符串转数字   l         1.CRT函数     ASCII UNICODE TCHAR VS2005 int atoi _wtoi _tstoi, ...

  9. VC++中忽略所有默认库纯Win32 API编译及链接 - 计算机软件编程 - Wangye's Space

    原始链接: VC++中忽略所有默认库纯Win32 API编译及链接 - 计算机软件编程 - Wangye's Space 我们在用VC++编写Windows程序的时候可能会发现一般可执行体(.EXE) ...

最新文章

  1. Google Protocol Buffers和java字符串处理控制
  2. 着眼未来!2019未来杯高校AI挑战赛圆满落幕
  3. matlab-画个拱桥和倒影?
  4. opnet平台中切换模块的理解——切换的建模
  5. wireshark 分析mptcp ecn语句
  6. 带小手的文档怎么复制
  7. mysql 查看修改连接数据库_mysql查看最大连接数和修改mysql数据库最大连接数方法...
  8. Vivado 2020.1 仿真时卡在executing simulate step
  9. 健康体检信息管理系统方案/案列/软件/APP/小程序/网站
  10. java 案例(售卖橙子)
  11. 回扣应该怎么给——某人的经验
  12. c++ 序列化库iguana使用总结
  13. 【MOD】函数判别性别
  14. 养成良好的编程习惯-一个库一个文件夹
  15. 日本研发5nm取得重大进展,和美国远离EUV,ASML陷入众叛亲离境地
  16. python输出棱形及对称三角
  17. GopherChina第一天小结
  18. 想做自媒体副业,有什么领域可推荐?
  19. python数据结构: 有序表
  20. uniapp 拉起微信客服功能

热门文章

  1. 源码读不会,小白两行泪!
  2. 疯了吧!面试官 5 连问一个 TCP 连接可以发多少个 HTTP 请求?
  3. 并发的核心:CAS 是什么?Java8是如何优化 CAS 的?
  4. Spring Boot是如何实现自动配置的?
  5. 从头搭建 IntelliJ IDEA 环境,从放弃到爱不释手!
  6. 聊聊 Spring Cloud Config
  7. Makefile:条件编译
  8. map:map指向最后一个元素?指向第一个元素?
  9. 计算机网络 公有IP和私有IP介绍
  10. Android --- 单一控件覆盖其他控件的方法