宽字符

Unicode

宽字符有很多种,Unicode只 是宽字符编码的一种实现,每个字符用 16位 表示。

Unicode的产生是为了解决许多8位无法标识的东西。

ASCII

这是世界上流行的编码,每个字符用 7位 表示。但是这套编码不能表示一些其他国家的字符,可以说这套编码是为美国设计的。
C语言的宽字符是基于 wchar_t 数据类型的。这个数据类型被定义在多个头文件中,包括 WCHAR.H
   typedef  unsigned short wchar_t;

所以 wchar_t  数据类型和一个无符号整型一样,都是 16位 宽。

可以这样定义一个包含单个宽字符的变量

wchar_t c = 'A' ;

也可以这样定义:
wchar_t c = L'A' ;                                     但这通常是不需要的。

变量 c 是一个 2 byte 的值0x0041,这是Unicode中字母A的代表。它在内存中的存储是按照高位在后,低位在前存储的。

所以在内存中是这样,0x41,0x00。
可以这样定义一个已初始化的指向宽字符串的指针:

 wchar_t *p = L"Hello!";

  注意:大写字母 L 紧接着左引号。这向编译器表明这个字符串将用宽字符存储,也就是说每个字符 2 byte。

   这个字符串一共 14 byte,因为字符串结尾需要加 0 。
   指针变量 p 需要 4 byte的存储空间,因为在汇编里 cs:ip 表示代码执行的指针。cs : 段位移    ip : 偏移地址。


宽字符库函数
   大家都知道     char *pc = "Hello!";               iLength = strlen(pc);                   iLength = 6

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

    此时编译的话编译器会发出警告,意思是strlen函数在被定义是为接收一个指向char的指针,但这里收到的是一个指向无符号       短整型的指针。但仍可以运行。      但     iLength =1  这是为什么呢?
   因为这些字符串数据是这样存储在内存中的   48 00 65 00 6c 00 6F 00 21 00
   strlen函数仍试图找字符串的长度,计算第一个字节作为字符,但然后认为第二个字节 0 为字符串的结尾。所以长度为 1 。

  因此对于宽字符的数据处理也引入了专门的库函数。

  宽字符版本的strlen函数被称为 wcslen("string"),并定义在STRING.H 和 WCHAR.H 中。

   对于宽字符和单字符你可能想用同一个函数名来使用,当是宽字符时函数就调用宽字符的函数,否则就不变
  答案是可以的。可以使用 TCHAR.H 的头文件。这个头文件并不是ANSI C 标准的一部分,所以其中定义的每一个
   函数和宏都有一个下划线前缀。

   在介绍使用之前,先来介绍下面两个数据类型:   CHAR              WCHAR


   在 WINNT.H 中定义了:
                        typedef   char   CHAR;                               用来定义 8位 的字符

                       typedef   wchar_t    WCHAR;                     用来定义 16位 的字符

    当然其中也定义了字符指针:
     这些都是 8位 字符串指针                                    指每次指针移动偏移 8位


                       typedef  CHAR * PCHAR,* LPCH,* NPSTR, * PSTR;
                       typedef  CONST CHAR * LPCCH, * PCCH, * LPCSTR, * PCSTR;

这里的 PCHAR,LPCH,NPSTR,PSTR 都是CHAR * 的别名,以后定义一个指针就可以直接用别名了。

     例如 :CHAR * P     和   PCHAR P     是同一个意思,懂了吧

    不过我也不知道为啥要弄这么多的别名。。。

     也有 16位 的字符串指针                                       指每次指针移动偏移 16 位

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

     另外,前缀 N 和 L 分别是表示"近"(near),和"远"(long),指的是 16位 Windows系统中的两种大小不同的指针

   不过在win32中near,和long指针没有区别,所以不必管它。

好了,介绍结束了,现在来谈谈用法。

  那么如何使用同一个函数名来实现不同的功能呢
  在包含头文件 TCHAR.H 的情况下,举个例子:如果一个命名为_UNICODE的标识符被定义了,那么就实现处理宽字符串的功能,否则就仍是处理单字节字符的字符串。
                                                   
   #ifdef  UNICODE                                                                                    
     typedef  WCHAR  TCHAR, * PTCHAR          既将WCHAR别名为TCHAR,也将WCHAR * 别名为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

 现在便可以用同一个函数来处理宽字符,或者单字符了。


Windows 函数调用:
   就以MessageBox函数为例吧,该函数是存在于动态链接库USER.EXE 中的。


    那么什么叫做动态链接库呢?
     简单的说就是共享函数库,它可以为许多的进程在运行时来调用它,这个函数库是独立存在的,进程里并不包函这些函数,只在用到的是后去动态链接库调动它。

同样,MessageBox为支持Unicode也有两个入口点MessageBoxA(ASCII版),另一个则是MessageBoxW(宽字符版),
 不叫MessageBoxU哦,千万别记错了。
    同样可以用同样的方法来实现。


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

猜你喜欢

转载自blog.csdn.net/qq_41413835/article/details/80508289