TCHAR, WCHAR, LPSTR, LPWSTR, LPCTSTR<三>

来源:互联网 发布:加拿大订酒店软件 编辑:程序博客网 时间:2024/03/29 10:34

TCHAR, WCHAR, LPSTR, LPWSTR, LPCTSTR究竟是神马!!!<三>



接着上面继续介绍。。。

TCHAR宏是针对单个字符的,你可以直接声明TCHAR的数组。如果你想表示字符指针或者const字符指针,该是下面的哪一个呢?
// ANSI characters foo_ansi(char*); foo_ansi(const char*); /*const*/ char* pString; // Unicode/wide-string foo_uni(WCHAR*); wchar_t* foo_uni(const WCHAR*); /*const*/ WCHAR* pString; // Independent foo_char(TCHAR*); foo_char(const TCHAR*); /*const*/ TCHAR* pString;
在看了上文介绍的TCHAR字符数组之后,你就会选择最后一个。它表示起来更加灵活。你需要引入头文件Windows.h。注意:如果你工程直接或者简介包含了Windows.h,就不再需要引入TCHAR.h

为了更好的理解,先来回顾一般字符串的版本。比如strlen:
size_t strlen(const char*);
可能别表示成:
size_t strlen(LPCSTR);
标识符LPCSTR是通过typedef来定义的:
typedef const char* LPCSTR; 
也就是这样的意思:
LP - Long PointerC - ConstantSTR - String
从本质上讲,意味着(长)指针,指向一个常量字符串。

我们来使用新的命名风格表示strcpy:
LPSTR strcpy(LPSTR szTarget, LPCSTR szSource);
szTarget的类型是LPSTR,类型中没有C,它是这样定义的:
typedef char* LPSTR;
注意:szSource是LPCSTR类型的,因为strcpy函数并不会改变源字符串数组,因此便带有const属性,返回值的类型不是const的:LPSTR。

这些str版本的函数都是基于ANSI字符串的操作。但是我们想要2字节表示的Unicode字符串例子。同样,宽字符版本的str函数也是有提供的。例如,计算宽字符表示的字符串长度的函数:wcslen:
size_t nLength;nLength = wcslen(L"Unicode");
wcslen函数的定义:
size_t wcslen(const wchar_t* szString); // 或者 WCHAR*
也可以用下面的代替:
size_t wcslen(LPCWSTR szString);
LPCWSTR的定义如下:
typedef const WCHAR* LPCWSTR;// const wchar_t*
拆开来分析:
  • LP - Pointer
  • C - Constant
  • WSTR - Wide character String
同样,strcpy等价于wcscpy,对于以下Unicode字符串:
wchar_t* wcscpy(wchar_t* szTarget, const wchar_t* szSource)
可以使用下面替换
LPWSTR wcscpy(LPWSTR szTarget, LPWCSTR szSource);

存在的等价wcs-函数和str-函数。 str-函数将用于ANSI字符串而wcs-函数将用于Unicode字符串。

不过,我前面建议使用Unicode字符集函数,而不是ANSI或者YCHAR标记的函数。原因很简单:应用程序必须只是Unicode,甚至你不应该关心代码以ANSI编译时候的可移植性。但为了此文章的完整性,在这里提及了通用的映射。


计算字符串的长度,你也许会使用_tcslen函数(它是一个宏)。本质上来说,它的定义如下:
size_t _tcslen(const TCHAR* szString);
或者:
size_t _tcslen(LPCTSTR szString);
其中:
  • LP - Pointer
  • C - Constant
  • T = TCHAR
  • STR = String
根据具体的工程设置,LPCTSTR将被映射成LPCSTR(ANSI)或者LPCWSTR(Unicode)。
注意:strlen,wcslen或者_tcslen将会返回字符串的字符个数,而不是字节数。

因此,_tcscpy的定义:
size_t _tcscpy(TCHAR* pTarget, const TCHAR* pSource);
可以被翻译成:
size_t _tcscpy(LPTSTR pTarget, LPCTSTR pSource);



使用例子来说明。

int main(){    TCHAR name[] = "Saturn";    int nLen; // Or size_t    lLen = strlen(name);}

使用ANSI字符集编译,代码将会成功通过编译,因为TCHAR被翻译成char,因此 name就是char的数组。调用strlen计算name长度也是正常的工作。
然而,当使用Unicode编译的时候(在工程设置中字符集设置成:"Use Unicode Character Set"),便会出错:
  • error C2440: 'initializing' : cannot convert from 'const char [7]' to 'TCHAR []'
  • error C2664: 'strlen' : cannot convert parameter 1 from 'TCHAR []' to 'const char *'
程序员可能会以这种方式修改错误:
TCHAR name[] = (TCHAR*)"Saturn";
这并不起效,因为从TCHAR*到TCHAR[7]的转换不会成功。当本地ANSI字符串传递Unicode版本的函数时也会出错:
nLen = wcslen("Saturn");// ERROR: cannot convert parameter 1 from 'const char [7]' to 'const wchar_t *'
然而,这样的错误能使用C风格的类型转换实现:
nLen = wcslen((const wchar_t*)"Saturn");
你可能感觉你又学会了使用指针的新的技能!你错了,虽然编译通过,但是得不到正确的结果!而且在很多情况下会引起访问异常。

字符串"Satrun"由7字节的序列组成:
'S' (83)'a' (97)'t' (116)'u' (117)'r' (114)'n' (110)'\0' (0)但是当你给wcslen传递相同的字节数时,它将认为两个字节表示一个字符。因此前两个字节[97,83]会被当做一个字符来处理,第二个字节是[117,116]...
因此类型转换的时候需要特别注意。

于是,你应该这样进行改进:
TCHAR name[] = _T("Saturn");
它会将字符串从7个字节转换成14个字节来存储。调用wcslen也就会变为:
wcslen(L"Saturn");

0 0
原创粉丝点击