转自 http://www.cnblogs.com/procoder/archive/2009/11/25/windows-mobile-ansi-unicode-string.html
背景
开发过Windows Mobile和Wince(Windows Embedded CE)的开发者,特别是Native C++开发者,或多或少都遇到过ANSI字符集和Unicode字符集的转换问题。本文试图把Windows Mobile和Wince(Windows Embedded CE)开发的字符集问题讲明白,其实这个题目有点ambitious和aggressive,就当成标题党吧。
简介
本文试图通过一篇文章讲清楚Windows Mobile和Wince(Windows Embedded CE) Native C++开发中字符集的转换问题。从字符集的概念入手,讲述Wince支持的所有字符串类型,以及各种类型的转换方法,最后给出使用建议。
什么是字符集
字符集(Character Set)是映射关系,其定义了字符和编码的关系。这里编码通常来说是1和0的bit。当前流行的计算机系统任何数据存储最终都表达为1和0。而这些1和0在不同字符集下映射成不同含义的字符。
计算机发明和使用初期,存储设备都十分的昂贵,科学家们想尽办法来节省成本,因此开始的是,最常见的字符集是单字节字符集(Signle-byte),所谓单字节字符集就是使用一个byte来代表一个字符,单字符集的典型是ASCII (American Standard Code for Information Interchange),你看这不是国籍标准,仅仅是美国标准,压根就没有考虑咱们感受,咱们从甲骨文开始发展汉字,美国人看到就A~Z几个字母。
这个ASCII 表,学过C语言的人都学过,以前考试也用到,需要背下来的。
ANSI(American National Standards Institute) 是在ASCII 7bit 编码标准 (ASA X3.4-1963)的基础上,加入了欧洲字母发展出来的一个标准。
但是单字节字符集有个最要命的缺点是一个byte只要8个bit,也就是最多表示256 (28)个可见和不可见的字符。 对于英语国家可能是够用的,但是对于说中文的国家,汉字是没办法通过256个字符表达的。因此慢慢出来国际标准的字符集Unicode。
Wince与Unicode
对于刚刚接触Windows Mobile和Wince(Windows Embedded CE) Native C++开发的人来说,会有这样的想法:Windows Mobile和Wince仅仅支持Unicode,不支持ANSI的。TinyXML是使用ANSI string的,但是Wince使用Unicode,那么TinyXML不能使用在Wince和Windows Mobile中。等等…… 其实这些想法有些错误,Wince是一个Unicode系统,没错,这表示Wince里面所有字符串处理代码都是基于Unicode编码,但是不表示Wince不支持ANSI。我们同样可以继续在Wince中使用ANSI,例如使用std::string, char[]等。
但是为什么会有这些误区呢,先看一下下面的编译错误。
error C2664: 'wprintf' : cannot convert parameter 1 from 'const char [21]' to 'const wchar_t *'
error C2664: 'DeleteFileW' : cannot convert parameter 1 from 'const char [21]' to 'LPCWSTR'
我敢保证刚刚接触Windows Mobile和Wince(Windows Embedded CE) Native C++开发的人10个有9个甚至10个都碰到过上述问题。在调用Win32 API的时候,使用MFC,WTL的接口的时候都会碰到这样的问题,因为我们习惯使用char*,std::string,但是恰恰Win32 API,MFC和WTL的函数入口中的字符串为Unicode,因此发生上述的编译错误。不知道为什么大家碰到这个错误后会形成一个错误的想法:Wince只是支持Unicode,不支持ANSI了。其实Wince还是支持ANSI的,我们定义单字符的char数组,甚至可以通过C Runtime在Console中打印出ANSI string。
char ansiStr[] = "I am ANSI string"; printf(ansiStr);
Wince支持的字符串
既然Wince支持ANSI和Unicode,那什么时候用ANSI,什么时候用Unicode,下面我从在Wince开发中常常用到字符串讲起,然后讲述字符串的转换以及使用建议。
char*
char*和char[]没有本质的区别,都是指向内存的指针。ANSI版本的Win32的API中的字符串都是使用char*。 由于Win32的API是语言无关的,因此这些参数其实传递的是一段应该存放字符串的内存的指针。(很拗口,但是确实这样,呵呵)。在ANSI环境下使用纯粹C开发,程序是离不开char*的。
wchar_t *
LPWSTR, PWSTR等宏定义其实都是wchar_t*的定义, 最常见的LPCWSTR是const wchar_t*的宏定义。wchar_t表示16位Unicode字符。wchar_t*和wchar_t[]用来定义Unicode字符串。在Unicode版本下,所有Win32的API的字符串都由char*变成了wchar_t*了。
这个可以看一下头文件的预编译。例如以winbase.h的DeleteFile API为例。
WINBASEAPI BOOL WINAPI DeleteFileA( LPCSTR lpFileName ); WINBASEAPI BOOL WINAPI DeleteFileW( LPCWSTR lpFileName ); #ifdef UNICODE #define DeleteFile DeleteFileW #else #define DeleteFile DeleteFileA #endif // !UNICODE
在ANSI版本DeleteFile为DeleteFileA,参数的字符串定义为LPCSTR,也就是const char*,而Unicode版本的DeleteFile为DeleteFileW,参数字符串定义变成了LPCWSTR,也就是const wchar_t*。
决定DeleteFile到底是DeleteFileA或者DeleteFileW是由预编译宏 UNICODE 来决定的。
这个宏可以在项目属性里面配置,如下图:
当选择Use Unicode Character Set时候,预编译会增加宏UNICODE和_UNICODE。
但是需要注意的是,如果目标平台为Windows Mobile或者Wince,不管是否选择Use Unicode Character Set,UNICODE和_UNICODE的预编译都会加上,也就是说Wince下所有Win32 API都是Unicode版本的。
CString
CString最初在MFC里面封装,ATL和WTL分别封装了CString,这三个不同封装的CString具有语义兼容性,也就是他们提供的接口是相同的。使用CString的好处是可以同时兼容ANSI和Unicode,如下例子:
CString str = "Independent String";
m_wndPic.SetWindowText(str);
m_wndPic是一个CStatic控件,上面的代码不管在ANSI或者在Unicode都能使用,无需更改。
下面以ATL CString为例子讲述CString是如何同时支持支持ANSI或者Unicode的。
typedef CAtlString CString;
typedef CStringT< TCHAR, StrTraitATL< TCHAR > > CAtlString;
CString存储字符串的类型由TCHAR来决定的,而TCHAR又是由UNICODE预编译来决定,见下面的宏定义。
#ifdef UNICODE // r_winnt typedef WCHAR TCHAR, *PTCHAR; #else /* UNICODE */ // r_winnt typedef char TCHAR, *PTCHAR; #endif /* UNICODE */
以此CString使用字符串类型根据预编译选项来自动决定。
std::string
STL里面的string,封装的是单字节字符,由于其跨平台的特性,我编写的代码中大量使用std::string,其实准确来说我大量使用STL。例如我一般使用std::string来操作TinyXML。抛开Wince平台不说,使用std::string基本上没有缺点,可以跨任何支持标准C++的平台。可是在Wince和Windows Mobile下做开发,情况有点不一样,因为std::string封装的是单字节字符,所以如果需要调用Win32的API,使用MFC,ATL和WTL的功能时都需要转型,这姑且算是一个缺点吧,但是熟悉了转换以后,使用std::string一点问题都没有。
std::wstring
STL里面的string的Unicode版本,和std::string一样,使用了unicode字符进行封装。其实std::wstring我用的不多,用std::string已经够了。
如何转换Wince支持的字符串
既然Windows Mobile和Wince(Windows Embedded CE)支持上述的字符串,那么我们开发的时候会碰到这些字符串直接相互转换的问题,下面通过例子演示如何转换。
转换过程我推荐使用ATL的宏,关于ATL的宏可以参考 ATL and MFC String Conversion Macros
这些宏的命名规范为
CSourceType2[C]DestinationType[EX]
SourceType/DestinationType | Description |
A | ANSI character string. |
W | Unicode character string. |
T | Generic character string (equivalent to W when _UNICODE is defined, equivalent to A otherwise). |
OLE | OLE character string (equivalent to W). |
A表示ANSI string,W表示Unicode string,T表示通用string,根据预编译来决定类型。OLE和W一样,我从来不用OLE。
例如CT2CA就是通用string转成ANSI string。
转换到char*
void ConvertToCharArray() { char ansiStr[255] = "ANSI string"; wchar_t unicodeStr[255] = _T("Unicode string"); //use _T() convert const string to wchar_t string CString cstr("ATL CString"); std::string stlStr("STL string"); std::wstring stlWStr(_T("STL wstring")); //use _T() convert const string to wchar_t string printf("All string convert to char*\n"); strcpy(ansiStr, CT2CA(unicodeStr)); printf("Convert from wchar_t*, %s\n", ansiStr); strcpy(ansiStr, CT2CA(cstr)); printf("Convert from CString, %s\n", ansiStr); strcpy(ansiStr, stlStr.c_str()); printf("Convert from std::string, %s\n", ansiStr); strcpy(ansiStr, CT2CA(stlWStr.c_str())); printf("Convert from std::wstring, %s\n", ansiStr); }
例子中用到了ATL CString,如果新建的是Win32项目需要加入ATL支持,方法可以参考: 在Windows Mobile和Wince(Windows Embedded CE)下Win32项目加入ATL支持
上面讲过ATL CString和WTL以及MFC CString语义相同,因此本文所有CString的代码在MFC下同样有效。
转换到wchar_t*
void ConvertToWCharArray() { char ansiStr[255] = "ANSI string"; wchar_t unicodeStr[255] = _T("Unicode string"); //use _T() convert const string to wchar_t string CString cstr("ATL CString"); std::string stlStr("STL string"); std::wstring stlWStr(_T("STL wstring")); //use _T() convert const string to wchar_t string printf("All string convert to wchar_t*\n"); wcscpy(unicodeStr, CComBSTR(ansiStr)); wprintf(_T("Convert from char*, %s\n"), unicodeStr); wcscpy(unicodeStr, cstr); wprintf(_T("Convert from CString, %s\n"), unicodeStr); wcscpy(unicodeStr, CComBSTR(stlStr.c_str())); wprintf(_T("Convert from std::string, %s\n"), unicodeStr); wcscpy(unicodeStr, stlWStr.c_str()); wprintf(_T("Convert from std::wstring, %s\n"), unicodeStr); }
这里使用了微软推荐的CComBSTR(),而不是CA2W()。
转换到CString
void ConvertToCString() { char ansiStr[255] = "ANSI string"; wchar_t unicodeStr[255] = _T("Unicode string"); //use _T() convert const string to wchar_t string CString cstr("ATL CString"); std::string stlStr("STL string"); std::wstring stlWStr(_T("STL wstring")); //use _T() convert const string to wchar_t string printf("All string convert to CString\n"); cstr = ansiStr; wprintf(_T("Convert from char*, %s\n"), cstr); cstr = unicodeStr; wprintf(_T("Convert from wchar_t*, %s\n"), cstr); cstr = stlStr.c_str(); wprintf(_T("Convert from std::string, %s\n"), cstr); cstr = stlWStr.c_str(); wprintf(_T("Convert from std::wstring, %s\n"), cstr); }
转换到std::string
void ConvertToStlString() { char ansiStr[255] = "ANSI string"; wchar_t unicodeStr[255] = _T("Unicode string"); //use _T() convert const string to wchar_t string CString cstr("ATL CString"); std::string stlStr("STL string"); std::wstring stlWStr(_T("STL wstring")); //use _T() convert const string to wchar_t string printf("All string convert to STL string\n"); stlStr = ansiStr; printf("Convert from char*, %s\n", stlStr.c_str()); stlStr = CT2CA(unicodeStr); printf("Convert from wchar_t*, %s\n", stlStr.c_str()); stlStr = CT2CA(cstr); printf("Convert from CString, %s\n", stlStr.c_str()); stlStr = CT2CA(stlWStr.c_str()); printf("Convert from std::wstring, %s\n", stlStr.c_str()); }
转换到std::wstring
void ConvertToStlWstring() { char ansiStr[255] = "ANSI string"; wchar_t unicodeStr[255] = _T("Unicode string"); //use _T() convert const string to wchar_t string CString cstr("ATL CString"); std::string stlStr("STL string"); std::wstring stlWStr(_T("STL wstring")); //use _T() convert const string to wchar_t string printf("All string convert to STL wstring\n"); stlWStr = CComBSTR(ansiStr); wprintf(_T("Convert from char*, %s\n"), stlWStr.c_str()); stlWStr = unicodeStr; wprintf(_T("Convert from wchar_t*, %s\n"), stlWStr.c_str()); stlWStr = cstr; wprintf(_T("Convert from CString, %s\n"), stlWStr.c_str()); stlWStr = CComBSTR(stlStr.c_str()); wprintf(_T("Convert from std::string, %s\n"), stlWStr.c_str()); }
纯C Runtime库转换
有时候使用Win32进行纯C的开发,例如进行今日插件的开发,不使用ATL,WTL,MFC以及STL的情况下,也会有转换char*和wchar_t*的需求,但是不能使用ATL的宏,下面演示如何使用C Runtime库来转换。
void ConvertToWCharArrayUsingCRuntime() { char ansiStr[255] = "ANSI string"; wchar_t unicodeStr[255] = _T("Unicode string"); //use _T() convert const string to wchar_t string printf("Convert to char* from wchar_t* using C Runtime library.\n"); sprintf(ansiStr, "%S", unicodeStr); printf("Convert from wchar_t*, %s\n", ansiStr); } void ConvertToCharArrayUsingCRuntime() { char ansiStr[255] = "ANSI string"; wchar_t unicodeStr[255] = _T("Unicode string"); //use _T() convert const string to wchar_t string printf("Convert to wchar_t* from char* using C Runtime library.\n"); swprintf(unicodeStr, _T("%S"), ansiStr); wprintf(_T("Convert from char*, %s\n"), unicodeStr); }
使用建议
上面讲述了Windows Mobile和Wince(Windows Embedded CE)支持那么多字符串,那么我们到底如何选择使用的字符串呢?其实这个没有准则,我下面谈一下我的经验。这不是准则,所以只做参考之用。
一.尽量避免使用char*和wchar_t*
除了以下情况,不得不使用char*和wchar_t*时,大部分时候尽量避免使用char*和wchar_t*。
情况1
做今日组件开发,只是使用Win32,如果不依赖于ATL,WTL,MFC和STL,那么没得选择只能使用char*和wchar_t*。
关于今日组件的开发,可以参考:
关于在Windows Mobile下今日插件使用WTL的问题
情况2
封装DLL或者通用静态库提供给第三方使用,例如TinyXML, CppUnitLite这样的类库,他们内部都在char*基础上实现字符串处理类,这样库就不依赖于ATL,WTL,MFC和STL了。
关于TinyXML, CppUnitLite可以参考:
Windows Mobile和Wince下使用TinyXML进行Native C++的开发
Wince和Windows Mobile下native C++的单元测试
Windows Mobile下使用CppUnitLite输出测试结果
情况3
封装DLL给.NET Compact Framework使用,接口函数只能使用char*和wchar_t*,不能使用CString和std::string。
关于DLL的封装,可以参考:
Windows Mobile和Wince(Windows Embedded CE)下如何封装Native DLL提供给.NET Compact Framework进行调用
Windows Mobile和Wince(Windows Embedded CE)下封装Native DLL进一步探讨
情况4
可以使用char*和wchar_t*包括一些字符串常量,用于替换宏定义。
除了上述情况以外,应当尽量避免使用char*和wchar_t*,而是用CString,std::string等封装好的字符串类。
二.程序需要同时支持PC和Window Mobile版本时使用CString
如果使用C++加上ATL,WTL或者MFC开发,程序需要同时支持Windows桌面版和Windows Mobile以及Wince,可以考虑使用CString。CString可以很好的兼容ANSI和Unicode版本。
例如我封装的一个SQL Server Compact的数据库访问类,使用到CString,这个类可以支持PC和Windows Mobile。可以参考:
Windows Mobile下Native C++访问SqlCe的封装
三.程序需要跨平台时使用std::string
程序不仅仅用于windows平台,而且用于Linux,Unix,BSD等平台,可以考虑使用std::string,我一般不使用std::wstring,觉得没有这个必要,使用std::string在需要的时候转换就可以了。但是如果追求更高的跨平台性,那只能使用char*和wchar_t*了,连STL都不依赖。
我个人喜欢使用std::string,因为我大量使用STL。在设计的时候把界面和处理逻辑分开,处理逻辑内部统一使用std::string以及STL的容器。需要界面交互出来,或者调用Win32的时候进行字符串的转换。
可以进一步参考的文章
出处: http://procoder.cnblogs.com
本 作品由 Jake Lin创作,采用 知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。 任何转载必须保留完整文章,在显要地方显示署名以及原文链接。如您有任何疑问或者授权方面的协商,请 给我留言。
我刚刚看了一下wince里面的wchar.h。好像是字符串操作,没有字符串转换。swprintf放到stdlib.h去了。
wchar.h的定义:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
inline
int
fwide(
FILE
*,
int
_M)
{
return
(_M); }
inline
int
mbsinit(
const
mbstate_t
*)
{
return
(1); }
inline
const
wchar_t
*wmemchr(
const
wchar_t
*_S,
wchar_t
_C,
size_t
_N)
{
for
(; 0 < _N; ++_S, --_N)
if
(*_S == _C)
return
(_S);
return
(0); }
inline
int
wmemcmp(
const
wchar_t
*_S1,
const
wchar_t
*_S2,
size_t
_N)
{
for
(; 0 < _N; ++_S1, ++_S2, --_N)
if
(*_S1 != *_S2)
return
(*_S1 < *_S2 ? -1 : +1);
return
(0); }
inline
wchar_t
*wmemcpy(
wchar_t
*_S1,
const
wchar_t
*_S2,
size_t
_N)
{
wchar_t
*_Su1 = _S1;
for
(; 0 < _N; ++_Su1, ++_S2, --_N)
*_Su1 = *_S2;
return
(_S1); }
inline
wchar_t
*wmemmove(
wchar_t
*_S1,
const
wchar_t
*_S2,
size_t
_N)
{
wchar_t
*_Su1 = _S1;
if
(_S2 < _Su1 && _Su1 < _S2 + _N)
for
(_Su1 += _N, _S2 += _N; 0 < _N; --_N)
*--_Su1 = *--_S2;
else
for
(; 0 < _N; --_N)
*_Su1++ = *_S2++;
return
(_S1); }
inline
wchar_t
*wmemset(
wchar_t
*_S,
wchar_t
_C,
size_t
_N)
{
wchar_t
*_Su = _S;
for
(; 0 < _N; ++_Su, --_N)
*_Su = _C;
return
(_S); }
}
/* end of extern "C" */
inline
wchar_t
*wmemchr(
wchar_t
*_S,
wchar_t
_C,
size_t
_N)
{
return
((
wchar_t
*)wmemchr((
const
wchar_t
*)_S, _C, _N)); }
inline
wchar_t
*wcschr(
wchar_t
*_S,
wchar_t
_C)
{
return
((
wchar_t
*)wcschr((
const
wchar_t
*)_S, _C)); }
inline
wchar_t
*wcspbrk(
wchar_t
*_S,
const
wchar_t
*_P)
{
return
((
wchar_t
*)wcspbrk((
const
wchar_t
*)_S, _P)); }
inline
wchar_t
*wcsrchr(
wchar_t
*_S,
wchar_t
_C)
{
return
((
wchar_t
*)wcsrchr((
const
wchar_t
*)_S, _C)); }
inline
wchar_t
*wcsstr(
wchar_t
*_S,
const
wchar_t
*_P)
{
return
((
wchar_t
*)wcsstr((
const
wchar_t
*)_S, _P)); }
|
你说的对L这个作用很大,我现在偏向用_T()来代替L,自动选择字符集。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
#define _T(x) __TEXT(x)
#ifdef UNICODE // r_winnt
#ifndef _TCHAR_DEFINED
typedef
WCHAR
TCHAR
, *
PTCHAR
;
typedef
WCHAR
TBYTE
, *
PTBYTE
;
typedef
wchar_t
_TCHAR;
typedef
wchar_t
_TSCHAR;
typedef
wchar_t
_TUCHAR;
typedef
wchar_t
_TXCHAR;
typedef
wint_t
_TINT;
#define _TCHAR_DEFINED
#endif /* !_TCHAR_DEFINED */
typedef
LPWSTR
LPTCH, PTCH;
typedef
LPWSTR
PTSTR
,
LPTSTR
;
typedef
LPCWSTR
PCTSTR
,
LPCTSTR
;
typedef
LPWSTR
LP;
#define __TEXT(quote) L##quote // r_winnt
#else /* UNICODE */ // r_winnt
#ifndef _TCHAR_DEFINED
typedef
char
TCHAR
, *
PTCHAR
;
typedef
unsigned
char
TBYTE
, *
PTBYTE
;
#define _TCHAR_DEFINED
#endif /* !_TCHAR_DEFINED */
typedef
LPSTR
LPTCH, PTCH;
typedef
LPSTR
PTSTR
,
LPTSTR
;
typedef
LPCSTR
PCTSTR
,
LPCTSTR
;
#define __TEXT(quote) quote // r_winnt
#endif /* UNICODE */
|
Win32编程中最好使用Windows类型 包含了windows.h之后 可以使用以下类型 一般有这样的对应关系:
字符 字符串 常量字符串 字符串文字量
TCHAR LPTSTR LPCTSTR TEXT("char") 或者 _T"char"
WCHAR LPWSTR LPCWSTR L"char"
CHAR LPSTR LPCSTR "char"
LP是long ptr的意思 表示长整型指针
C是表示常量的意思
CHAR是字符类型 STR是字符串类型
除非有特别需要 一般都使用T系列的 这可以保证你的字符和字符串总是和API匹配
CString
CString最初在MFC里面封装,ATL和WTL分别封装了CString,这三个不同封装的CString具有语义兼容性,也就是他们提供的接口是相同的。使用CString的好处是可以同时兼容ANSI和Unicode,如下例子:
CString str = "Independent String";m_wndPic.SetWindowText(str);m_wndPic是一个CStatic控件,上面的代码不管在ANSI或者在Unicode都能使用,无需更改。
CString str = "Independent 在win32下要改成加_T()的吧?
2 egmkang的回复真有营养 文章配评论更全面呢 另外昨天还遇到一个问题 很有意思 你看看
http://www.devdiv.net/thread-18413-1-1.html
3 最后还有个很重要的方面 网上资料很少 http://www.devdiv.net/thread-18328-1-1.html
注意那个flywhc的回复 他提到了BOM
搞不好可以写一个"字符集"问题进一步探讨啦 哈哈
你这么认真,他日必定大有作为。
这个代码是对的,那些代码都经过测试才放上去。
那个地方是CString的=号运算符重载的时候转型。请看下面的代码。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
template
<>
class
ChTraitsBase<
wchar_t
>
{
public
:
typedef
wchar_t
XCHAR;
typedef
LPWSTR
PXSTR;
typedef
LPCWSTR
PCXSTR;
typedef
char
YCHAR;
typedef
LPSTR
PYSTR;
typedef
LPCSTR
PCYSTR;
};
CStringT& operator=( _In_opt_z_ PCYSTR pszSrc )
{
// nDestLength is in XCHARs
int
nDestLength = (pszSrc != NULL) ? StringTraits::GetBaseTypeLength( pszSrc ) : 0;
if
( nDestLength > 0 )
{
PXSTR pszBuffer = GetBuffer( nDestLength );
StringTraits::ConvertToBaseType( pszBuffer, nDestLength, pszSrc);
ReleaseBufferSetLength( nDestLength );
}
else
{
Empty();
}
return
( *
this
);
}
static
void
ConvertToBaseType(_Out_cap_(nDestLength)
wchar_t
* pszDest,
int
nDestLength,
_In_count_(nSrcLength)
const
char
* pszSrc, _In_
int
nSrcLength = -1)
throw
()
{
// nLen is in wchar_ts
::MultiByteToWideChar(_AtlGetConversionACP(), 0, pszSrc, nSrcLength, pszDest, nDestLength);
}
|
CString默认会按需转换的啊
可我试了下 在Mobile下不行啊
找个地方放一个临时变量 CString str="ab";
error C2440: “初始化”: 无法从“const char [2]”转换为“ATL::CStringT<BaseType,StringTraits>”
这是什么情况呢?我是在MFC程序下试的
得CString str=_T("ab");这样才行或者加L才行 有点费解
CString又不是系统API 而且是个模板类 不知道咋回事
在CString上按F12可以看到
typedef ATL::CStringT< wchar_t, StrTraitMFC< wchar_t > > CStringW;
typedef ATL::CStringT< char, StrTraitMFC< char > > CStringA;
typedef ATL::CStringT< TCHAR, StrTraitMFC< TCHAR > > CString;
同时兼容ANSI和Unicode是指不要考虑char或者wchar_t么?
我之前的意思是如果"在ANSI或者在Unicode都能使用"
兼容平台的话 那就用_T()可以让CString自动处理是ANSI还是Unicode字符串了吧? 那就不用转了?
CString str;
str = "ab";
或者
CString str("ab");
这样就可以了。
同时兼容ANSI和Unicode是指_T("ab")在ANSI等于 "ab",而在Unicode等于L"ab"。而CString同样道理,在ANSI使用char*作为存储,在Unicode中使用wchar_t*作为存储。
CString str = _T("ab");
在ANSI等于
CString str = "ab";
在Unicode等于
CString str = L"ab";
如果使用了CString str = _T("ab");那么没有字符转换过程(字符转换指char*与wchar_t*的转换)。但是都有=号运算符的重载,分别重载了参数 const char*与 const wchar_t*,还是根据ANSI和Unicode来重载不同的参数。