Programing with LPSTR、LPCSTR、LPTSTR、LPCTSTR

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型变量。但是这是一种不安全的使用方法。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值