1. 程式人生 > >Windows下的字串處理(1)

Windows下的字串處理(1)

最近感覺Windows下的字串處理有點紊亂,準備系統學習下。在此做點筆記。

Unicode或者寬字元都沒有改變char資料型態在C中的含義。char繼續表示1個位元組的儲存空間,sizeof (char)繼續返回1。

理論上,C中1個位元組可比8位長,但對我們大多數人來說,1個位元組(也就是1個char)是8位寬。

C中的寬字元基於wchar_t資料型態,它在幾個表頭檔案包括WCHAR.H中都有定義,像這
樣:
typedef unsigned short wchar_t ;
因此,wchar_t資料型態與無符號短整數型態相同,都是16位寬。

wchar_t c = 'A' ;
變數c是一個雙位元組值0x0041,是Unicode表示的字母A。(然而,因為Intel微處理器從最
小的位元組開始儲存多位元組數值,該位元組實際上是以0x41、0x00的順序儲存在記憶體中。如果
檢查Unicode文字的計算機儲存應注意這一點。)

還可以用下面的語句定義寬字元陣列:
static wchar_t a[] = L"Hello!"
該字串也需要14個位元組的儲存空間,sizeof (a) 將返回14。索引陣列a可得到單獨的字元。
a[1] 的值是寬字元「e」,或者0x0065。


----------------------------------------------

char * pc = "Hello!" ;
我們可以呼叫
iLength = strlen (pc) ;
這時變數iLength將等於6,也就是字串中的字元數。

wchar_t * pw = L"Hello!" ;
再次呼叫strlen :
iLength = strlen (pw) ;

首先一條警告,繼續執行結果是1.

原因:

字串「Hello!」中的6個字元佔用16位:
0x0048 0x0065 0x006C 0x006C 0x006F 0x0021
Intel處理器在記憶體中將其存為:
48 00 65 00 6C 00 6C 00 6F 00 21 00
假定strlen函式正試圖得到一個字串的長度,並把第1個位元組作為字元開始計數,但接著
假定如果下一個位元組是0,則表示字串結束。
這個小練習清楚地說明了C語言本身和執行時期連結庫函式之間的區別。編譯器將字串
L"Hello!" 解釋為一組16位短整數型態資料,並將其儲存在wchar_t陣列中。編譯器還處理

陣列索引和sizeof操作符,因此這些都能正常工作,但在連結時才新增執行時期連結庫函式,

例如strlen。這些函式認為字串由單位元組字元組成。遇到寬字串時,函式就不像我們所
希望那樣執行了。

所以提出了wcslen、wprintf等寬字元版的庫函式。但是這樣寫通用性就差了,所以又提出了

_tcslen、TCHAR。那麼在書寫字串時為了通用,提出了_T(x)巨集。

如果定義了_UNICODE識別符號,那麼一個稱作__T的
巨集就定義如下:
#define __T(x) L##x
這是相當晦澀的語法,但合乎ANSI C標準的前置處理器規範。那一對井字號稱為「貼上符
號(token paste)」,它將字母L新增到巨集引數上。因此,如果巨集引數是"Hello!",則L##x
就是L"Hello!"。
如果沒有定義_UNICODE識別符號,則__T巨集只簡單地定義如下:
#define __T(x) x
此外,還有兩個巨集與__T定義相同:
#define _T(x)__T(x)
#define _TEXT(x)__T(x)
在Win32 console程式中使用哪個巨集,取決於您喜歡簡潔還是詳細。基本地,必須按下述
方法在_T或_TEXT巨集內定義字串文字:
_TEXT ("Hello!")
這樣做的話,如果定義了_UNICODE,那麼該串將解釋為寬字元的組合,否則解釋為8位的
字元字串。


---------------------------------------

寬字元和 Windows

WINNT.H定義了新的資料型態,稱作CHAR和WCHAR:
typedef char CHAR ;
typedef wchar_t WCHAR ; // wc


WINNT.H表頭檔案進而定義了可用做8位字串指標的六種資料型態和四個可用做const
8位字串指標的資料型態。這裡精選了表頭檔案中一些實用的說明資料型態語句:
typedef CHAR * PCHAR, * LPCH, * PCH, * NPSTR, * LPSTR, * PSTR ;
typedef CONST CHAR * LPCCH, * PCCH, * LPCSTR, * PCSTR ;
字首N和L表示「near」和「long」,指的是16位Windows中兩種大小不同的指標。在Win32
中near和long指標沒有區別。
類似地,WINNT.H定義了六種可作為16位字串指標的資料型態和四種可作為const 16
位字串指標的資料型態:
typedef WCHAR * PWCHAR, * LPWCH, * PWCH, * NWPSTR, * LPWSTR, * PWSTR ;
typedef CONST WCHAR * LPCWCH, * PCWCH, * LPCWSTR, * PCWSTR ;
至此,我們有了資料型態CHAR(一個8位的char)和WCHAR(一個16位的wchar_t),
以及指向CHAR和WCHAR的指標。與TCHAR.H一樣,WINNT.H將TCHAR定義為一般的
字元型別。如果定義了識別符號UNICODE(沒有底線),則TCHAR和指向TCHAR的指標就
分別定義為WCHAR和指向WCHAR的指標;如果沒有定義識別符號UNICODE,則TCHAR
和指向TCHAR的指標就分別定義為char和指向char的指標: