寬字符


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 中。

   在介紹使用之前,先來介紹下面兩個數據類型:   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 ;
typedef LPWSTR LPTCH, PTCH, PTSTR, LPTSTR ;
typedef LPCWSTR LPCTSTR ;
#else 
typedef char TCHAR, *PTCHAR ;
typedef LPSTR LPTCH, PTCH, PTSTR, LPTSTR ;
typedef LPCSTR LPCTSTR ;
#endif

同時用來選擇字符處理函數,例如WINUSER.H中:

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

這 樣,我們只用一種類型(比如TCHAR)和一組函數(比如MessageBox)就方便地可以處理兩種編碼的程序,

而不用去條件判斷應該用char還是 wchar_t,

應該用MessageBoxA還是MessageBoxW。這些細節Windows.h等頭文件中已經為我們考慮了,

我們要做的只是在需要用Unicode時定義兩個符號。

 

另外提醒一下:

                  _UNICODE 是讓 C 函數使用 unicode
                    UNICODE  是讓 API 使用 unicode

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM