认识宽窄字节

我们知道ascii码表 可以用来表示256哥字符的字符集,但是像我们中文这种有上万个字符,很明显ascii已经无法满足我们字符的需求,Unicode字符的每个字节不是8位而是十六位宽度,它可以表示65536个字符,这里只是简单的介绍一下Unicode字符和ascii的区别 和在windows平编程使用二者的区别。
我们之前在C语言中的编程中会经常用到char类型来定义和存储字符和字符串 比如char c = 'a变量c需要一个字节的存储空间而且会用0X41被初始化 也就是ASCII码表对应的符号 char*p = "hello";p表示一个指向字符串的指针 这里p会占4个字节 而字符串会存储在静态区域 并且占7个字节包括结尾'\0'

宽字节

使用Unicode并不会改变C语言中的字符数据类型 char类型继续代表一个字节的存储空间 sizeof(char)继续表示 宽字节的表示方法 wchar_t数据类型 宽字节是这样被定义的 #typedef unsigned short wchar_t 表示位16位宽 表示方法
wchar_t c = 'A' 变量c是一个两字节的值0x0041 在内存中的存储是0x41,0x00 wchar_t *p = L"hello";大写字母的L向编译器表示这个字符串将用宽字符存储 每个字符占两个字节 p作为指针也还是需要四个字节的存储空间 但是这个字符串需要14个字节 每个字符都需要两个字节 '\0'也表示两个字节 当然也可以像char一样定义一个宽字符的数组 当然也可以在单个字符常量之前使用L前缀 这样它将会被解释为 宽字符
总结一下:char* char 都是窄字节,适配英文字母,随着国际化,,窄字节无法表示,所以引入宽字节,即unicode(规定任意字符占两个字节)  wchar-t 其原型是unsigned short

宽字符库函数

strlen()对应的是窄字符取字符串长度的函数
wchar_t * pw = "hello";
iLength = strlen(pw);
程序应该是6但是返回我们的是1 我们可以看看unicode的编码表示 0x0048 0x0065 0x006c 0x006c 0x006f 0x0021内存存储方式为 48 00 65 00 6c 00 6f 00 21 00我们会看到在第一个字节之后是00和'\0'是一样的,编译器会认为这就是字符串结束的标志 所以长度就是1(并不会计算'\0')的长度 当然,我们也有宽字符版本的strlen 叫做wcslen函数声明如下size_t _cdecl wcslen(const wchar_t *)
iLength = wcslen(pw);该函数返回结果是6,也就是字符串中的字符个数 在使用宽字符时候,字符串的字符长度没有改变,改变的是字节的长度

优缺点

界面开发 为了效率最好用unicode编码省去了系统转换  VS字符集配置  多字节是窄字节  Unicode是宽字节
优缺点:
unicode网络传输影响速度
如果我们希望生成两个版本的软件 一个使用Unicode一个使用ASCII字符串 那么运行库函数不同 变量不同以及宽字符L 这时候我们就需要一个通用的函数名字 它们既可以指向Unicode也可以指向非Unicode
如果_UNICODE 的标识符被定义 那么_tcslen就会被定义为wcslen #typedef _tcslen wcslen
如果_UNICODE没有被定义 那么_tcslen就被定义为strlen 同时也解决了数据类型的问题_UNICODE被定义 #typedef wchar_t TCHAR没有定义TCHAR就是char 当然我们还有L这个棘手的问题 如果_UNICODE被定义 #define _T(x) L##x##表示链接的意思 如果宏参数是"hello" 那么L##xx就是L"hello" 如果_UNICODE没有被定义那么_T()就被定义为#define __T(x) x宏_TEXT被定义为_T是一样的 _TEXT("hello!")如果_UNICDOE被定义了那么字符串的解释是由宽字符组成的 如果没有被定义 他将被解释为八位的字符串。
宏介绍完成了 接下来我们将介绍windows下的宽窄字符的应用

windows头文件

windows头文集对wchar_t包含着新的定义,这俩个新的数据类型被称为CHAR和WCHAR的数据类型

typedef char CHAR
typedef wchar_t WCHAR
C++

这是windows程序编程所推荐的数据类型 他们分别被用于定义8位或者16位的字符。此外还定义了可作为16位字符串指针的16位数据类型和可作为const 16位字符串指针的四种数据类型

typedef WCHAR* PWCHAR,*LPWCH,*PWCH,*NWPSTR,*LPWSTR,*PWSTR
typedef CONST WCHAR* LPCWCH,*PCWCH,*LPCWSTR,*PCWSTR
C++

前缀N和L表示16位windows系统的两种大小不同的指针 但是在win32中没有区别
还定义了可做8位字符串指针的六种数据类型和可用作const 8位字符串指针的四种数据类型

typedef CHAR *PCHAR,*LPCH,*PCH,*NPSTR,*PSTR
typedef CONST CHAR* LPCCH,*PCCH,*LPCSTR,*PCSTR
C++

这样我们就有了CHAR 和WCHAR以及各种指针 如果使用了通用字符类型,就要看UNICODE是否定义 来确定是CHAR还是WCHAR

#ifdef UNICODE
typedef WCHAR TCHAR,*PTCHAR;
typedef LPWSTR LPTCH,PTCH,PTSTR,LPTSTR;
typedef LPCWSTR LPCTSTR;
#else
typedef char TCHAR,*PTCHAR;
typedef LPSTR LPTCH,PTCH,PTSTR,LPTSTR;
typedef LPCSTR LPCTSTR;
#endif
C++

当我们编写windows程序时候 为了防止重复定义 我们可以包含其他头文件时优先包含windows的头文件
需要注意的是_T需要下划线而TEXT版本可以不加下划线
如果想明确使用8位字符变量或者字符串 就是用CHAR PCHAR 如果明确使用16位字符变量和字符串 可以使用WCHAR PWCHAR 并将L添加到引号前面
P代表指针  str字符串  L代表长指针  C标识常量 W标识宽字节  T标识通用类型

windows函数调用

int WINAPI MessageBox(HWND,LPCSTR,LPCSTR,UNIT);
该函数有两个入口点 一个是MessageBoxA-ASCII 一个名为MessageBoxW-UNICODE版 像这样的用字符串做参数的每个win32函数 都在操作系统中有两个入口点 程序会自动识别 就像在TCHAR一样
如果定义了_UNICODE 则函数为MessageBoxW() 没有定义就用MessageBoxA

#ifdef UNICODE
#define MessageBox MessageBoxW
#else
#define MessageBox MessageBoxA
#endif
C++

windows的字符串函数

windows定义了一组字符串函数 这些函数用来计算字符串长度 复制字符串 链接字符串和比较字符串
iLength = lstrlen(pString);
pString = lstrcpy(pString,pString);
pString = lstrcpyn(pString,pString);
pString = lstrcat(pString,pString);
iComp = lstrcmp(pString,pString);
iComp = lstrcmpi(pString,pString);
这些函数提供了与C运行库中对应的函数功能 当定义了UNICODE标识符 这些函数就接受宽字符串 否则只接受常规字符串。

小结

_T和_L的区别在于,_L不管你是以什么方式编译,一律以UNICODE方式保存。 #ifdef _UNICODE的时候
_T就是L
没有#ifdef _UNICODE的时
_T就是ANSI的
LPTSTR lpStr = new TCHAR[32];
TCHAR* szBuf = _T("Hello");
以上两句使得无论是在UNICODE编译条件下都是正确编译的。

给TA打赏
共{{data.count}}人
人已打赏
汇编语言编程学习

转移指令

2024-11-15 11:42:54

WinApi编程学习

windows程序设计

2024-11-15 14:51:51

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索

Powered by atecplugins.com