此文章是根據如下文章和自己的思考總結歸納整理出來的:
https://www.cnblogs.com/zhangdongsheng/archive/2011/08/16/2141513.html
http://www.voidcn.com/article/p-chwlarat-hs.html
字符集
首先要知道通常Windows平臺下的程序設計可以支持ANSI和UNICODE兩種編碼方法的字符串(Windows95 、98上不支持UNICODE標準)。
- ANSI:即多字節字符集(Multi-Byte Character System),它是編碼的一種類型,而不是某個特定編碼的名稱。它是不定長表示世界文字的編碼方式。ANSI編碼表示英文字符時用一個字節(同ASCII編碼),表示其他文字時就需要使用多字節(表示中文時用兩個字節)。
- Unicode:用兩個字節表示一個字符的編碼方式。比如字符'A'在ASCII下面用一個字節表示,而在Unicode下面用兩個字節表示,其中高字節用“0”填充。Unicode是定長表示世界文字的編碼方式,據統計,用兩個字節可以編碼現存的所有文字而沒有二義。
在visual studio中,可以再這裏設置字符集
WINDOWS數據類型
VC++中的char,wchar_t,TCHAR
大家一起做一個項目,經常發現有的人愛用strcpy等標準ANSI函數,有的人愛用_tXXXX函數,這個問題曾經搞的很混亂。爲了統一,有必要把來龍去脈搞清楚。
爲了搞清這些函數,就必須理請幾種字符類型的寫法。char就不用說了,先說一些wchar_t。wchar_t是Unicode字符的數據類型,它實際定義在<string.h>裏:
typedef unsigned short wchar_t;
不能使用類似 strcpy這樣的ANSI C字符串函數來處理wchar_t字符串,必須使用wcs前綴的函數,例如wcscpy。爲了讓編譯器識別Unicode字符串,必須以在前面加一個 “L”,例如:
wchar_t *szTest=L"This is a Unicode string.";
下面在看看TCHAR。如果你希望同時爲ANSI和Unicode編譯的源代碼,那就要include TChar.h。TCHAR是定義在其中的一個宏,它視你是否定義了_UNICODE宏而定義成char或者wchar_t。如果你使用了TCHAR,那麼就不應該使用ANSI的strXXX函數或者Unicode的wcsXXX函數了,而必須使用TChar.h中定義的_tcsXXX函數。另外,爲了解決剛纔提到帶“L”的問題,TChar.h中定義了一個宏:“_TEXT”。
以strcpy函數爲例子,總結一下:
.如果你想使用ANSI字符串,那麼請使用這一套寫法:
char szString[100];
strcpy(szString,"test");
.如果你想使用Unicode字符串,那麼請使用這一套:
wchar_t szString[100];
wcscpyszString,L"test");
.如果你想通過定義_UNICODE宏,而編譯ANSI或者Unicode字符串代碼:
TCHAR szString[100];
_tcscpy(szString,_TEXT("test"));
字符串及處理:使用TCHAR系列方案
使用TCHAR系列方案編寫程序
TCHAR是一種字符串類型,它讓你在以MBCS和UNNICODE來build程序時可以使用同樣的代碼,不需要使用繁瑣的宏定義來包含你的代碼。
TCHAR的引入,主要是在Tchar.h文件中,該文件包含這方面的重要的定義信息。
對於包含了對str函數或wcs函數進行顯式調用的代碼來說,無法非常容易地同時爲ANSI和Unicode對這些代碼進行編譯。本章前面說過,可以創建同時爲ANSI和Unicode進行編譯的單個源代碼文件。若要建立雙重功能,必須包含TChar.h文件,而不是包含String.h文件。
TChar.h文件的唯一作用是幫助創建ANSI/Unicode通用源代碼文件。它包含你應該用在源代碼中的一組宏,而不應該直接調用str函數或者 wcs函數。如果在編譯源代碼文件時定義了_UNICODE,這些宏就會引用wcs這組函數。如果沒有定義_UNICODE,那麼這些宏將引用str這組宏。
TCHAR的定義如下:
#ifdef UNICODE
typedef wchar_t TCHAR;
#else
typedef char TCHAR;
#endif
所以用MBCS來build時,TCHAR是char,使用UNICODE時,TCHAR是wchar_t。
還有一個宏來處理定義Unicode字符串常量時所需的L前綴。
#ifdef UNICODE
#define _T(x) L##x
#define _TEXT(x) L##x
#define __T(x) L##x
#else
#define _T(x) x
#define _TEXT(x) x
#define __T(x) x
#endif
## 是一個預處理操作符,它可以把兩個參數連在一起。如果你的代碼中需要字符串常量,在它前面加上_T宏。如果你使用Unicode來build,它會在字符串常量前加上L前綴。
TCHAR szNewText[] = _T("we love Bob!");
_UNICODE宏用於C運行期頭文件,而UNICODE宏則用於Windows頭文件。當編譯源代碼模塊時,通常必須同時定義這兩個宏。
像是用宏來隱藏SetWindowTextA/W的細節一樣,還有很多可以供你使用的宏來實現str***()和_mbs***()等字符串函數。例如,你可以使用_tcsrchr宏來替換strrchr()、_mbsrchr()和wcsrchr()。_tcsrchr根據你預定義的宏是_MBCS還是 UNICODE來擴展成正確的函數,就象SetWindowText所作的一樣。
不僅str***()函數有TCHAR宏。其他的函數如, _stprintf(代替sprinft()和swprintf()),_tfopen(代替fopen()和_wfopen())。 MSDN中"Generic-Text Routine Mappings."標題下有完整的宏列表。
下面來解釋下幾個指針類型的具體意思:
LPSTR: 32-bit指針指向一個字符串,每個字符佔1字節。相當於char *
LPCSTR:: 32-bit指針指向一個常量字符串,每個字符佔1字節。相當於const char *
LPTSTR: 32-bit指針每字符可能佔1字節或2字節,取決於Unicode宏是否定義。相當於TCHAR *(或_TCHAR *)
LPCTSTR: 32-bit指針指向一個常量字符串,每字符可能佔1字節或2字節,取決於Unicode宏是否定義。相當於const THCAR *(或const _TCHAR *)
LPWSTR: 32-bit指針指向一個Unicode字符串的指針,每個字符佔2字節。相當於wchar_t *
LPCWSTR: 32-bit指針指向一個Unicode字符串常量的指針,每個字符佔2字節。相當於const wchar_t *
LPBYTE: 32-bit指針指向一個字節的指針,相當於unsigned char *
(L表示long, P表示pointer,C表示constant,,T表示指針指向的字符佔的字節數取決於Unicode是否定義——即_T宏,W表示wide,STR就是string的意思)