MFC CString Wstring Char Wchar _T 关系及转换

最近做了下宽字符,窄字符的实验。发现了一系列的有趣东东。我发现我过去一直使用Ascii编码。现在发现unicode还是灰常有用的。

首先std::string std::wstring 和CString 这几个东东最好不要用于DLL的接口之中,不管是返回值还是传入的参数。当然编译时是不会
出错的,但是链接可能会有各种奇异的问题,比如不能识别CString等等。所以建议DLL接口还是使用LPCTSTR LPCSTR
LPCWSTR以及我们经常使用的char*. 反正是DLL接口中的类型越基础也好。当然你可以尝试使用复合类型。

这里的的LPCTSTR 就是const TCHAR , LPCSTR 就是const char , LPCWSTR就是 const
wchar_t*。LP就是指针的意思,C就是const,T就是TCHAR, W就是wchar_t, 然后大家都有STR的后缀。关于TCHAR,char,
以及wchar_t之间的关系,其实看你是否定义了_UNICODE宏,想要定义的话需要在编译的时候添加编译参数-
D_UNICODE即可。如果定义了这个宏,那么wchar_t就是TCHAR, 否则 TCHAR就是
char,其实这里就是为了灵活性。对于vs系列,想要识别unicode编码,需要在字符或者字符串前添加L,例如:

wchar_t a = L’a’; wchar_t *b = L"abc";

关于_T()的使用,或许就明了了,_T(“ab”) 就是L"ab" , _T(‘c’) 就是 L’c’, _T(x)的宏定义就是 L ## x,其意思就是将
L和x像字符串一样连接在一起。关于宏定义的各种用法,感兴趣的可以search.当然为了灵活性,这里也是使用了_T也有两个定义这个也与是否定义了_UNICOD
E宏有关系。

所谓窄字符其实就是ascii字符,这个东东只有1个字节。而宽字符有2个字节。这就是宽字和窄字的不同了。当然这里还有WORD和DWORD,这里的WORD其实就
是unsigned short,就是2个字节和wchar_t一样。而DWORD就是unsigned
long也就是4字节。根据特殊的应用,有不同的效果。不过说到底还是各种基础类型转来转去的。

关于各种类型的互相转换其实不是很简单,不过大都可以通过CString来转换。各种窄字符可以直接放入到CString构造函数中,它将自动的为所有的字符添加L.
让其成为unicode. 例如

const char * a = “abc”; CString s(a);

其实CString可以强制转换为LPCTSTR,如果想强制转换为其他的类型,最好考虑下是否有后遗症。但是强转为LPCTSTR是没有问题的。另外std::ws
tring本身是有wchar_t的数组构成的。而std::string本身是有char数组构成的。对于这些类型只需要调用
c_str()就可以转变为const wchar_t* 或者 const char*.另外因为string,wstring, CString这几个东东都有引
用计数的机制,所以在多线程编程中,尽量不要使用。另外对于CString而言,这个东西可以强制不使用引用计数机制,只需要调用lockBuffer即可。另外CS
tring转char* 如果是在Atl编程的情况下可以使用T2A()这个函数,对于其他可以调用WideCharToMultiByte()这个函数:

WideCharToMultiByte( __in UINT CodePage, __in DWORD dwFlags, __in_opt LPCWSTR
lpWideCharStr, __in int cchWideChar, __out_bcount_opt(cbMultiByte) LPSTR
lpMultiByteStr, __in int cbMultiByte, __in_opt LPCSTR lpDefaultChar, __out_opt
LPBOOL lpUsedDefaultChar);

这个东东有8个参数,不过一般你如果使用TCHAR* 转 char* 只需要使用其中的若干个。一般使用:WideCharToMultiByte(CP_ACP,
0, lpw, -1, lpa, nChars, NULL, NULL); lpw是你传入的TCHAR* or wchar_t, lpa是你最终的转换数组,
当然这个东东开始的内容需要自己分配,当然如果nChars这个是0的话,其实这个函数只是数了下宽字符的个数,然后将这个个数当做返回值返回,如果nChars这个
不为零,那么就是要填充的大小了,并且这个函数真正做了将宽字符转换成bytes的工作。CP_ACP这个是ascii页表。后两个产生对于未知的编码很有用,最后一
个你可以传入一个bool型的指针,如果所有的宽字符没有对应的多个窄字符,那么就会被倒数第二个参数替代,如果第二参数是NULL,那么就会使用?替代。当然此时这
个bool型指针的值就会变为true.

这样就可以各种类型的转换了。首先所有的类型转换为CString, 然后再用CString转为各种类型。