苏州类似青客的公寓:LPWSTR,LPCTSTR,LPTSTR

来源:百度文库 编辑:中财网 时间:2024/04/29 09:06:06

CString   和   LPCTSTR   可以说通用。   原因在于CString定义的自动类型转换,没什么奇特的,最简单的C++操作符重载而已。

常量字符串ansi和unicode的区分是由宏_T来决定的。但是用_T( "abcd ")时,   字符串 "abcd "就会根据编译时的是否定一_UNICODE来决定是char*   还是   w_char*。   同样,TCHAR   也是相同目的字符宏。   看看定义就明白了。简单起见,下面只介绍   ansi   的情况,unicode   可以类推。

ansi情况下,LPCTSTR   就是   const   char*,   是常量字符串(不能修改的)。
而LPTSTR   就是   char*,   即普通字符串(非常量,可修改的)。
这两种都是基本类型,   而CString   是   C++类,   兼容这两种基本类型是最起码的任务了。

由于const   char*   最简单(常量,不涉及内存变更,操作迅速),   CString   直接定义了一个类型转换函数
operator   LPCTSTR()   {......},   直接返回他所维护的字符串。

当你需要一个const   char*   而传入了CString时,   C++编译器自动调用   CString重载的操作符   LPCTSTR()来进行隐式的类型转换。  
当需要CString   ,   而传入了   const   char*   时(其实   char*   也可以),C++编译器则自动调用CString的构造函数来构造临时的   CString对象。

因此CString   和   LPCTSTR   基本可以通用。


但是   LPTSTR又不同了,他是   char*,   意味着你随时可能修改里面的数据,这就需要内存管理了(如字符串变长,原来的存贮空间就不够了,则需要重新调整分配内存)。

所以   不能随便的将   const   char*   强制转换成   char*   使用。
楼主举的例子
LPSTR   lpstr   =   (LPSTR)(LPCTSTR)string;
就是这种不安全的使用方法。

这个地方使用的是强制类型转换,你都强制转换了,C++编译器当然不会拒绝你,但同时他也认为你确实知道自己要做的是什么。因此是不会给出警告的。
强制的任意类型转换是C(++)的一项强大之处,但也是一大弊端。这一问题在   vc6   以后的版本(仅针对vc而言)中得到逐步的改进(你需要更明确的类型转换声明)。

其实在很多地方都可以看到类似
LPSTR   lpstr   =   (LPSTR)(LPCTSTR)string;
地用法,这种情况一般是函数的约束定义不够完善的原因,   比如一个函数接受一个字符串参数的输入,里面对该字符串又没有任何的修改,那么该参数就应该定义成   const   char*,   但是很多初学者弄不清const地用法,或者是懒,   总之就是随意写成了   char*   。   这样子传入CString时就需要强制的转换一下。

这种做法是不安全的,也是不被建议的用法,你必须完全明白、确认该字符串没有被修改。

CString   转换到   LPTSTR   (char*),   预定的做法是调用CString的GetBuffer函数,使用完毕之后一般都要再调用ReleaseBuffer函数来确认修改   (某些情况下也有不调用ReleaseBuffer的,同样你需要非常明确为什么这么做时才能这样子处理,一般应用环境可以不考虑这种情况)。

同时需要注意的是,   在GetBuffer   和   ReleaseBuffer之间,CString分配了内存交由你来处理,因此不能再调用其他的CString函数。

LPSTR、LPWSTR、LPCSTR、LPCWSTR、LPTSTR、LPCTSTR的区分与转化(转)

首先在编译程序时经常会遇到这种问题:

错误 1 error C2664: “CWnd::MessageBoxW”: 不能将参数 1 从“const char [3]”转换为“LPCTSTR”

 

1、觉得很烦,一般的做法就是不管三七二十一,在字符串前面加一个‘L’:

如调用函数FUN(LPCTSTR str)时,不能  FUN("HELLO");     而是FUN(L"HELLO");

通常这样做都比较能解决问题。

 

2、或者还可以用_T(), 即 FUN(_T("HELLO"));   _T() 的别名还有 _TEXT(), TEXT()。

 

稍微研究了下,BSTR,LPSTR,LPWSTR,LPCTSTR,LPTSTR等这些让人头晕的东东。(还是C#里简单啊,直接tostring)

 

BSTR:是一个OLECHAR*类型的Unicode字符串,是一个COM字符串,带长度前缀,与VB有关,没怎么用到过。

 

LPSTR:即 char *,指向以'/0'结尾的8位(单字节)ANSI字符数组指针

LPWSTR:即wchar_t *,指向'/0'结尾的16位(双字节)Unicode字符数组指针

 

LPCSTR:即const char *

LPCWSTR:即const wchar_t *

 

LPTSTR:LPSTR、LPWSTR两者二选一,取决于是否宏定义了UNICODE或ANSI

LPCTSTR: LPCSTR、LPCWSTR两者二选一,取决于是否宏定义了UNICODE或ANSI,如下是从MFC库中拷来的:

#ifdef UNICODE

    typedef LPWSTR LPTSTR;

    typedef LPCWSTR LPCTSTR;

#else

    typedef LPSTR LPTSTR;

    typedef LPCSTR LPCTSTR;

#endif

 

3、相互转换方法:

LPWSTR->LPTSTR:   W2T();
LPTSTR->LPWSTR:   T2W();
LPCWSTR->LPCSTR: W2CT();
LPCSTR->LPCWSTR: T2CW();

ANSI->UNICODE:     A2W();

UNICODE->ANSI:     W2A();

另外,CString转为CStringW方法(通过一个wchar_t数组来转)

 CString str;

 CStringW strw;
 wchar_t *text = new wchar_t[sizeof(wchar_t) * str.GetLength()];
 MultiByteToWideChar(CP_ACP,0,str,-1,text,str.GetLength());
 strw = text;

 

4、另外,还可以强行转换,不过不一定能成功

 

5、还有_bstr_t ( 对BTSTR的封装,需要#include ),也可将单字节字符数组指针转为双字节字符数组指针,还没怎么没用到过。



char :单字节变量类型,最多表示256个字符,

wchar_t :宽字节变量类型,用于表示Unicode字符,

它实际定义在里:typedef unsigned short wchar_t。

为了让编译器识别Unicode字符串,必须以在前面加一个“L”,定义宽字节类型方法如下:

    wchar_t c = `A' ;
wchar_t * p = L"Hello!" ;
wchar_t a[] = L"Hello!" ;

其中,宽字节类型每个变量占用2个字节,故上述数组a的sizeof(a) = 14

TCHAR / _T( ) :
如果在程序中既包括ANSI又包括Unicode编码,需要包括头文件tchar.h。TCHAR是定义在该头文件中的宏,它视你是否定义了_UNICODE宏而定义成:
定义了_UNICODE:    typedef wchar_t TCHAR ;
没有定义_UNICODE: typedef char TCHAR ;

#ifdef UNICODE
typedef char TCHAR;
#else
typede wchar_t TCHAR;
#endif
_T( )也是定义在该头文件中的宏,视是否定义了_UNICODE宏而定义成:
定义了_UNICODE:    #define _T(x) L##x
没有定义_UNICODE: #define _T(x) x
注意:如果在程序中使用了TCHAR,那么就不应该使用ANSI的strXXX函数或者Unicode的wcsXXX函数了,而必须使用tchar.h中定义的_tcsXXX函数。

以strcpy函数为例子,总结一下:


//如果你想使用ANSI字符串,那么请使用这一套写法: 
char szString[100]; 
strcpy(szString,"test"); 
//如果你想使用Unicode字符串,那么请使用这一套: 
wchar_t szString[100]; 
wcscpy(szString,L"test"); 
//如果你想通过定义_UNICODE宏,而编译ANSI或者Unicode字符串代码: 
TCHAR szString[100]; 
_tcscpy(szString,_TEXT("test"));

CSDN:superarhow说: 不要再使用TCHAR和_T了!他分析了原因后总结:如 果您正开始一个新的项目,请无论如何也要顶住压力,直接使用UNICODE编码!切记!您只需要对您的组员进行10分钟的培训,记住strcpy用 wcscpy,sprintf用swprintf代替,常数前加L,就可以了!它不会花您很多时间的,带给您的是稳定和安全!相信偶,没错的!!

一、 在字符串前加一个L作用:
   如  L"我的字符串"    表示将ANSI字符串转换成unicode的字符串,就是每个字符占用两个字节。
  strlen("asd")   =   3;  
  strlen(L"asd")   =   6;
  二、  _T宏可以把一个引号引起来的字符串,根据你的环境设置,使得编译器会根据编译目标环境选择合适的(Unicode还是ANSI)字符处理方式
   如果你定义了UNICODE,那么_T宏会把字符串前面加一个L。这时 _T("ABCD") 相当于 L"ABCD" ,这是宽字符串。
   如果没有定义,那么_T宏不会在字符串前面加那个L,_T("ABCD") 就等价于 "ABCD"
三、TEXT,_TEXT 和_T 一样的
如下面三语句:  
  TCHAR   szStr1[]   =   TEXT("str1");  
  char   szStr2[]   =   "str2";  
  WCHAR   szStr3[]   =   L("str3");  
  那么第一句话在定义了UNICODE时会解释为第三句话,没有定义时就等于第二句话。  
  但二句话无论是否定义了UNICODE都是生成一个ANSI字符串,而第三句话总是生成UNICODE字符串。  
  为了程序的可移植性,建议都用第一种表示方法。  
  但在某些情况下,某个字符必须为ANSI或UNICODE,那就用后两种方法。