3 MFC字符串
3.1 MFC下的常用字符串數據類型表示的含義
L:Long 長 P:Point 指針 C:Const 常量 W:Wchar_t 寬字符 T:TCHAR STR:String 字符串
在看看MFC下各種數據類型的定義:
typedef char *LPSTR;typedef const char *LPCSTR; typedef wchar_t *LPWSTR; typedef const wchar_t *LPCWSTR; typedef wchar_t WCHAR; #ifdef UNICODE typedef LPCWSTR LPCTSTR; typedef WCHAR TCHAR; #else typedef LPCSTR LPCTSTR; typedef char TCHAR; |
3.2 MFC下提供的ATL轉換宏(寬字節 <-> 多字節)
T2A T2W T2CA T2CW W2A W2CA W2T W2CT A2W A2CW A2T A2CT
T:TCHAR 2:To C:CONST A:CHAR(ANSI) W:WCHAR
先到atlconv.h頭文件下看看這些宏的定義,
3.2.1 USES_CONVERSION
注意int _convert; (_convert);這種用法是爲了屏蔽編譯器的警告:未引用的局部變量。。。
#ifndef _DEBUG |
可見,USES_CONVERSION宏定義了一些轉換所需要的變量,如_convert。所以使用那些宏的時候必須加上該宏。
3.2.2 以A2W爲例說明宏轉換過程
3.2.2.1 A2W多字節轉換爲寬字節
這裏就用到了USES_CONVERSION宏定義的_convert變量
#define A2W(lpa) (\ |
3.2.2.2 ATLA2WHELPER 多字節轉換爲寬字節
#define ATLA2WHELPER AtlA2WHelper
AtlA2WHelper實際上還是在調用MultiByteToWideChar,即多字節轉換爲寬字節
Ret_opt_z_cap_(nChars) inline LPWSTR WINAPI AtlA2WHelper(_Out_z_cap_(nChars) LPWSTR lpw, _In_z_ LPCSTR lpa, _In_ int nChars, _In_ UINT acp) throw() ATLASSERT(lpa != NULL); |
3.2.2.3 alloca 從堆上分配以字節爲單位的內存
#define alloca _alloca
_alloca:該函數從堆上分配以字節爲單位的內存,返回void *
void *_alloca(
size_t size
);
3.2.2.4 用法舉例
USES_CONVERSION;//USES_CONVERSION是ATL中的一個宏定義,用於編碼轉換,它定義了轉換宏所需的一些局部變量 WCHAR *pWch = L"WCHAR* TO CHAR*"; CHAR *pCh = W2A(pWch); TCHAR *pTch = _T("TCHAR* TO CHAR*"); CHAR *pCh2 = T2A(pTch); |
3.2.3 USES_CONVERSION使用注意
使用USES_CONVERSION一定要小心,它們從堆棧上分配內存,直到調用它的函數返回,該內存不會被釋放。如果在一個循環中,這個宏被反覆調用幾萬次,將不可避免的產生stackoverflow。但是考慮到棧空間的尺寸(默認2M),使用時要注意幾點:
1、只適合於進行短字符串的轉換;
2、不要試圖在一個次數比較多的循環體內進行轉換;
3、不要試圖對字符型文件內容進行轉換,因爲文件尺寸一般情況下是比較大的;
4、對情況 2 和 3,要使用 MultiByteToWideChar() 和 WideCharToMultiByte();
5、將字符轉換封裝到函數裏面
void DoA2W() |
3.3 CString類
Header |
Use for |
|
cstringt.h |
MFC-only string objects |
必須使用在MFC程序中,需要MFC靜態或動態庫幷包含頭文件<afxwin.h> |
atlstr.h |
Non-MFC string objects |
可以使用在非MFC程序中,只需包含<atlstr.h>非常好用,支持Unicode字符集 |
具體MSDN中有詳細的介紹
3.4 淺談_T、_TEXT、TEXT、L
MSDN中對於L的說明有一大堆英文,不過主要的就是:L是用來標誌一個字符(串)爲寬字符(串)
寬字符和多字節字符的說明如下:(引用自網絡)
寬字符,wide character,該字符集內每個字符使用相同的位長;
多字節字符,multibyte character,每個字符可以是一到多個字節不等,而某個字節序列的字符值由字符串或流(stream)所在的環境背景決定。
當你在VS2005以上版本的IDE工作時,可以選擇工作於這兩種不同的編碼方式下,而在Unicode方式下,則要對字符(串)常量前添加L來告訴編譯器它是寬字符
而MS爲我們定義了好幾個相關的宏,下面來一一說明:
_T //定義於tchar.h _TEXT //同樣定義於tchar.h,具體如下: #define _T(x) __T(x) #define _TEXT(x) __T(x)
#ifdef _UNICODE #define __T(x) L ## x //第210行 #else #define __T(x) x //第858行 #endif |
TEXT //定義於winnt.h #define TEXT(quote) __TEXT(quote)
#ifdef UNICODE #define __TEXT(quote) L##quote #else /* UNICODE */ #define __TEXT(quote) quote #endif /* UNICODE */ |
當我看到這裏的時候,一下子頭暈了,不知道大家有沒有注意到下面兩個問題:
1.這三個宏分別在兩個不同的文件被定義,看上去一個是運行時的頭文件,一個是Win的頭文件
2.前面兩個根據_UNICODE來確定宏內容,另一個則是根據UNICODE
那如果要同時使用這三個宏的話,那不是要同時定義_UNICODE和UNICODE?帶着問題,我把項目的屬性修改一下
當設置爲Unicode編碼的時候,編譯器命令選項中的確同時加入了_UNICODE和UNICODE
看來這應該又是MS的歷史遺留問題拉,搜索一下才發現:(引自網絡)
Jeffrey Richter在《Windows核心編程》中說,_UNICODE宏用於C運行期頭文件,而UNICODE宏則用於Windows頭文件.當編譯源代碼模塊時,通常必須同時定義這兩個宏.
看IDE自動生成的代碼,大都使用TEXT這個,應該是因爲IDE生成的都是基於Win的代碼,使用這個也很正常吧
從上面的分析可得:
這幾個宏的效果都是一個的,還是建議大家有事沒事都加上其中一個(_T、_TEXT、TEXT)
而L嘛,個人認爲還是不要在代碼中直接使用