【TCHAR、_T與_TEXT】【strcpy、wcscpy與_tcscpy】

(內容出自《把脈VC++》,挺好的一本書,下面內容是我整理摘錄的兩小節,順便吐槽微軟還真是整天把C搞的多複雜,讓人找來找去)

4.5.3  TCHAR、_T與_TEXT

計算機最初使用的不是UNICODE,最初的系統和程序都採用的是ANSI或者MBCS,那麼,問題來了:我們開發程序的時候,是採用char還是wchar_t?觀察如下代碼:

char msg[] = "學習C++"; 

當我們準備採用wchar_t時,則需要改成:

wchar_t msg[] = L"學習C++"; 

太麻煩了!幸運的是,Visual C++的開發者預知到了這樣的麻煩,他們從而爲此造出了一批宏,這些宏看起來亂七八糟的,但是確實解決了我們的問題,且看一段代碼:

TCHAR msg[] = _T("學習C++"); 

這段代碼中,msg到底是char數組還是wchar_t數組呢?Visual C++的解釋是,如果需要它是char數組,那麼它就是char數組;否則,它就是wchar_t數組。這樣的魅力來源於宏TCHAR的定義:

typedef   unsigned   char   CHAR;  
typedef   unsigned   wchar_t   WCHAR;   
 
#ifdef   UNICODE  
    typedef   wchar_t   TCHAR;   
#else  
    typedef   unsigned   char   TCHAR;  
#endif

由此可以看出,CHAR實際上就是unsigned char,WCHAR爲wchar_t,而TCHAR根據是否支持UNICODE而不同。宏UNICODE由此變得尤其重要,當我們定義了UNICODE宏,就相當於告訴了編譯器:我準備採用UNICODE版本。這個時候,TCHAR就會搖身一變,由unsigned char變成了wchar_t。

Visual C++項目屬性中都包含一項字符集的設置,如圖4-14所示。很容易理解,它與宏UNICODE之間存在着某種關係(還有宏MCBS,爲了簡化討論,在此省略)。

 
(點擊查看大圖)圖4-14  在Visual C++中設置項目採用的字符集

前面分析了TCHAR,接下來再來看看_T的含義:

#define _T(x)       __T(x)  
#define _TEXT(x)    __T(x)  
 
#ifdef   UNICODE  
    #define __T(x)      L ## x  
#else  
    #define __T(x)      x  
#endif 

同理,當UNICODE宏被定義,"_T("學習C++")"會解釋成"L"學習C++"",否則它只將其解釋成""學習C++""。

因此,我們建議這樣書寫代碼:

TCHAR msg[] = _T("學習C++"); 

除TCHAR之外,Windows還定義了一系列的包含T的宏:

#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

 

4.5.4  strcpy、wcscpy與_tcscpy

C++標準庫函數提供了字符和字符串的操作函數,並提供了其UNICODE版本,如:

char *strcpy(char *strDestination, const char *strSource);  
wchar_t *wcscpy(wchar_t *strDestination, const wchar_t *strSource); 

wcscpy()即爲strcpy()的寬字符版本,與_T類似的,Visual C++提供了類似的同名函數:

#ifdef  UNICODE   
    #define _tcscpy     wcscpy  
#else  
    #define _tcscpy     strcpy  
#endif 

因此我們建議這樣書寫代碼:

TCHAR src[] = _T("學習C++");  
TCHAR dest[20];  
_tcscpy(dest, src); 

比如,在使用printf()的時候,我會嘗試使用_tprintf()。

同樣的版本問題一樣會困擾着main()函數:

main( int argc, char *argv[ ], char *envp[ ]);  
wmain( int argc, wchar_t *argv[ ], wchar_t *envp[ ]); 

再來看_tmain()的定義:

#ifdef  UNICODE   
    #define _tmain      wmain  
    #define _tWinMain   wWinMain  
#else  
    #define _tmain      main  
    #define _tWinMain   WinMain  
#endif 

這就是爲什麼Win32控制檯項目默認輸出,提供一個_tmain()函數的緣故。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章