文章目录
- 前言
- 一、宽窄字节简介
- 二、操作系统及VS编译器对宽窄字节的编码支持
- 1. 操作系统
- 2. 编译器
- 三、宽窄字符串的优缺点
- 四、宽窄字节数据类型
- 总结
前言
Windows 程序设计3:宽窄字节的区别及重要性。
一、宽窄字节简介
在C++中,常用的字符串指针就是char* ,字符串变量为string,内部也是对char* 的封装,但是并不了解这些跟宽窄字节有什么关系。
实际上,最早的系统都是窄字节的,也就是我们最常用的char,因为都是英文的一共就26个字母,再加上其他的一些符号标点,char就足够用了。无符号的char最多可以表示255个字符,已经足够。
后来随着操作系统的国际化,系统出现了很多语言版本。原来的char表示一个英文字符的方式已经无法表达一个中文汉字了。汉字有好几万个,单纯的char取值范围已经不够了。此时有人想到,一个char表示不下那就用两个char来表示一个汉字。因此,数字、字母等仍用窄字节,也就是一个char来表示;一个汉字或全角字符等使用两个char来表示。
虽然这样可以基本解决问题,即在中文系统上能正常显示中文、在其他语言系统上也能够正常显示,但是如果想把一个在中文系统上写的软件拿到日文或韩文等其他语言的系统上就会出现乱码,汉字是无法正常显示的。同理,其他语言的软件拿到中文系统上也会出现乱码。
那么为了解决这样国际化的问题,微软在Windows系统中引入了宽字节的功能,即Unicode。Unicode中规定任意一个字符都占用两个字节,即两个char。无论是字符还是字母、数字、汉字都占用两个字节。用两个char难免造成不方便,因此微软定义了一个新的类型:wchar_t,其原型实际上就是unsigner short,占用两个字节。
二、操作系统及VS编译器对宽窄字节的编码支持
1. 操作系统
Windows提供了两种类型的API函数,如MessageBox函数,实际上MessageBox函数只是一个宏,其对应了两个版本的函数:MessageBoxA和MessageBoxW,在VS编译器中使用时系统会根据是否定义了_UNICODE宏来进行判断当前工程使用宽字节的Unicode编码还是窄字节编码,以此来决定使用哪个版本的函数。如果没有定义,则使用窄字节的MessageBoxA;如果定义了就使用宽字节的MessageBoxW。
右键MessageBox,点击转到定义
可以看到该宏的具体定义
可以利用Depends工具查看动态链接库中的函数,见https://blog.csdn.net/qq_59940419/article/details/144721964?spm=1001.2014.3001.5502,MessageBox在User32.dll中,打开如下路径:C:\Windows\System32,找到User32.dll将其拖入到Depends工具中,可以找到两个函数。
其他的很多函数也都是这样进行区分宽窄字节的。大家可以自己看一看。
说明:Windows 2000以后的系统都是使用Unicode从头进行开发的,如果调用任何一个Windows API函数并传递一个ANSI即窄字节的字符串,那么系统会首先将字符串转换为Unicode,然后将Unicode即宽字节的字符串传递给操作系统。如果希望函数返回ANSI字符串,系统就会先将Unicode字符串转换为ANSI字符串,然后将结果返回给应用程序。进行这些字符串的转换需要占用系统的时间和内存,通过从头开始使用Unicode来开发应用程序,可以使得应用程序运行得更加高效。因此开发时建议使用宽字节。
2. 编译器
VC++6.0默认为窄字节编码。vs2005, vs2008, vs2010, vs2012, vs2013, vs2015, vs2017等等都是默认Unicode编码。也可以在工程中设置编码方式。
右键项目,点击属性
可以在字符集处调整编码方式
注意:从vs2013开始,如果要将工程默认的Unicode编码转为窄字节编码,需要安装多字节补丁。
三、宽窄字符串的优缺点
即便Unicode宽字节相对来说更好,但是其也有缺点。
一般来说,设计界面和跟字符串操作相关的,推荐使用宽字节。其他地方还是可以使用窄字节的,因为宽字节的占用空间是窄字节的二倍。这样的话在本机还好,如果涉及字符串的网络传输,那么传输量会偏大。所以也不是说什么时候都要使用Unicode宽字节。
在一个工程中,有的地方使用宽字节,有的地方使用窄字节(如一些代码逻辑和网络传输使用窄字节,界面设计使用宽字节),这就需要进行宽窄字节的转换。微软提供相应的API函数,直接使用即可。
四、宽窄字节数据类型
大家熟知的char, char* 都是窄字节的。常见的一些数据类型如下:
窄字节:
char, char* , const char*
CHAR, (PCHAR, PSTR, LPSTR), LPCSTR
Unicode宽字节:
wchar_t, wchar_t* , const wchar_t*
WCHAR, (PWCHAR, PWSTR, LPWSTR), LPCWSTR
_T通用类型:
TCHAR, (TCHAR* , PTCHAR, PTSTR, LPTSTR), LPCTSTR
其中,P代表指针的思想,STR表示字符串的意思,L是长指针的意思(在Win32平台下可以忽略),C表示const常量的意思,W表示wide宽字节的意思,T可以理解为通用类型的意思。
可以根据工程中是否定义_UNICODE宏,来判断当前工程的编码是宽字节还是窄字节,然后再定义成不同的类型。比如TCHAR类型,如果工程中定义了_UNICODE宏,那么就表明工程是宽字节编码的,其最终就被定义为wchar_t类型,如果工程中没有定义_UNICODE宏,就表明工程是窄字节编码的,其最终被定义为char类型。通用类型的优势在于,在修改了工程的编码格式之后不需要修改代码,因此更加建议使用通用类型。
总结
Windows 程序设计3:宽窄字节的区别及重要性。