UNICODE:用两个字节表示一个字符的方法。比如字符'A'在ASCII下面是一个字符,可'A'在UNICODE下面是两个字符,高字符用0填充,而且汉字'程'在ASCII下面是两个字节,而在UNICODE下仍旧是两个字节。UNICODE的用处就是定长表示世界文字,据统计,用两个字节可以编码现存的 所有文字而没有二义。
MBCS:多字节字符集,是不定长表示世界文字的一种编码。MBCS表示英文字母时就和ASCII一样(这也是我们容易把MBCS和ASCII搞混的原因),但表示其他文字时就需要用多字节。
WINDOWS下面的程序设计可以支持MBCS和UNICODE两种编码的字符串,具体用那种就看程序员定义了MBCS宏还是UNICODE宏。MBCS宏对应的字符串指针是char*(也即LPSTR),UNICODE对应的指针是unsigned short*(也即LPWSTR),为了写程序方便微软定义了类型LPTSTR,在MBCS下他就是char*,在UNICODE下它是unsigned char*,这样你就可以重定义一个宏进行不同字符集的转换了。
1. LPSTR、LPCSTR、LPTSTR、LPCTSTR的意义:
LPSTR:32-bit指针,指向一个字符串,每个字符占1字节,等价于char*
LPCSTR:32-bit指针,指向一个常字符串,每个字符占1字节,等价于const char*
LPTSTR:32-bit指针,指向一个字符串,每字符可能占1字节或2字节,取决于Unicode是否定义,等价于TCHAR *
LPCTSTR:32-bit指针,指向一个常字符串,每字符可能占1字节或2字节,取决于Unicode是否定义,等价于const TCHAR *
Windows使用两种字符集ANSI和UNICODE,前者就是通常使用的单字节方式,但这种方式处理像中文这样的双 字节字符不方便,容易出现半个汉字的情况。而后者是双字节方式,方便处理双字节字符。
Windows NT的所有与字符有关的函数都提供两种方式的版本,而Windows9x只支持ANSI方式。_T一般同字常数相关,如_T("Hello")。如果你编译一个程序为ANSI方式,_T实际不起任何作用。而如果编译一个程序为UNICODE方式,则编译器会把"Hello"字符串以UNICODE方式保存。_T和L的区别在于,不管你是以什么方式编译,L一律用UNICODE方式保存。
① L是表示字符串资源为Unicode的。
例如:wchar_t Str[] = L"Hello World!";//这个就是双子节存储字符
② _T是一个适配的宏,当#ifdef _UNICODE的时 候,_T就是L,没有#ifdef _UNICODE的时候,_T就是ANSI的。
例如:LPTSTR lpStr = new TCHAR[32];
TCHAR* szBuf = _T("Hello");
以上两句使得无论是在UNICODE编译条件下还是在MBCS编译条件下都是正确编译的。
MS推荐你使用相匹配的字符串函数,比如处理LPTSTR或者LPCTSTR的时候,不要用strlen ,而是要用_tcslen,否则在UNICODE的编译条件下,strlen不能处理wchar_t*的字符串。
T是非常有意思的一个符号(TCHAR、LPCTSTR、LPTSTR、_T()、_TEXT()...),它表示使用一种中间类型,既不明确表示使用MBCS,也不明确表示使用UNICODE。那到底使用哪种字符集在编译的时候才决定。
char*是指向ANSI字符数组的指针,其中每个字符占据8位(有效数据是除掉最高位的其他7位),这里保持了与传统的C,C++的兼容。LP的含义是长指针(long pointer)。LPSTR是一个指向以‘\0’结尾的ANSI字符数组的指针,与char*可以互换使用,在win32中较多地使用LPSTR。而LPCSTR中增加的‘C’的含义是“CONSTANT”(常量),表明这种数据类型的实例不能被使用它的API函数改变,除此之外,它与LPSTR是等同的。为了满足程序代码国际化的需要,业界推出了Unicode标准,它提供了一种简单和一致的表达字符串的方法,所有字符中的 字节都是16位的值,其数量也可以满足差不多世界上所有书面语言字符的编码需求,开发程序时使用Unicode(类型为wchar_t)是一种被鼓励的做法。LPWSTR与LPCWSTR由此产生,它们的含义类似于LPSTR与LPCSTR,只是字符数据是16位的wchar_t而不是char。
然后为了实现两种编码的通用,提出了TCHAR的定义:
如果定义_UNICODE,声明如下:typedef wchar_t TCHAR;
如果没有定义_UNICODE,则声明如下:typedef char TCHAR;
LPTSTR和LPCTSTR中的含义就是每个字符是这样的TCHAR。
CString类中的字符就是被声明为TCHAR类型的,它提供了一个封装好的类供用户方便地使用。
2. LPSTR、LPCSTR、LPTSTR、LPCTSTR之间的转换:
2.1 如何理解LPCTSTR类型?
L表示long,这是为了兼容Windows 3.1等16位操作系统遗留下来的,在win32中以及其他的32为操作系统中,long、near及far修饰符都是为了兼容的作用。没有实际意义。
P表示这是一个指针。
C表示是一个常量。
T表示在Win32环境中,有一个_T宏,这个宏用来表示你的字符是否使用UNICODE, 如果你的程序定义了UNICODE或者其他相关的宏,那么这个字符或者字符串将被作为UNICODE字符串,否则就是标准的ANSI字符串。
STR表示这个变量是一个字符串。
LPCTSTR就表示一个指向常固定地址的可以根据一些宏定义改变语义的字符 串。同样, LPCSTR就只能是一个ANSI字符串,在程序中我们大部分时间要使用带T的类型定义。LPCTSTR等价于const TCHAR *。
常量字符串ansi和unicode的区分是由宏_T来决定的。但是用_T("abcd")时,字符串"abcd"就会根据编译时是否定义了_UNICODE来决定是char*还是w_char*。同样,TCHAR 也是相同目的字符宏。 看看定义就明白了。简单起见,下面只介绍ansi的情况,unicode可以类推。
2.2 LPCTSTR、CString、LPTSTR的比较
① 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基本可以通用。
CString转换到LPCTSTR:
CString cStr;
const char *lpctStr = (LPCTSTR)cStr;
LPCTSTR转换到CString:
LPCTSTR lpctStr;
CString cStr = lpctStr;
② 而LPTSTR等价于char*,意味着程序员随时可能修改里面的数据,这就需要内存管理了(如字符串变长,原来的存贮空间就不够了,则需要重新调整分配内存)。所以不能随便的将const char*强制转换成char*使用,因为这涉及到了安全性问题。
例示:
LPSTR lpstr = (LPSTR)(LPCTSTR)string; //string为CString类对象
首先,先将CString类对象转换为LPCTSTR型变量,然后再强制转换为LPSTR型变量。但是这是一种不安全的使用方法。
转自http://www.cnblogs.com/tekson/archive/2009/07/09/1519687.html