zoukankan      html  css  js  c++  java
  • LPTSTR、 LPCSTR、LPCTSTR、LPSTR的来源及意义(转)

    UNICODE用两个字节表示一个字符的方法。比如字符'A'ASCII下面是一个字符,可'A'UNICODE下面是两个字符,高字符用0填充,而且汉字''ASCII下面是两个字节,而在UNICODE下仍旧是两个字节。UNICODE的用处就是定长表示世界文字,据统计,用两个字节可以编码现存的 所有文字而没有二义。  

    MBCS多字节字符集,是不定长表示世界文字的一种编码。MBCS表示英文字母时就和ASCII一样(这也是我们容易把MBCSASCII搞混的原因),但表示其他文字时就需要用多字节。

    WINDOWS下面的程序设计可以支持MBCSUNICODE两种编码的字符串,具体用那种就看程序员定义了MBCS宏还是UNICODE宏。MBCS宏对应的字符串指针是char*(也即LPSTR),UNICODE对应的指针是unsigned short*(也即LPWSTR),为了写程序方便微软定义了类型LPTSTR,在MBCS下他就是char*,在UNICODE下它是unsigned   char*,这样你就可以重定义一个宏进行不同字符集的转换了。

    1. LPSTRLPCSTRLPTSTRLPCTSTR的意义:

    LPSTR32-bit指针,指向一个字符串,每个字符占1字节,等价于char*

    LPCSTR32-bit指针,指向一个常字符串,每个字符占1字节,等价于const char*

    LPTSTR32-bit指针,指向一个字符串,每字符可能占1字节或2字节,取决于Unicode是否定义,等价于TCHAR *

    LPCTSTR32-bit指针,指向一个常字符串,每字符可能占1字节或2字节,取决于Unicode是否定义,等价于const TCHAR *

    Windows使用两种字符集ANSIUNICODE,前者就是通常使用的单字节方式,但这种方式处理像中文这样的双 字节字符不方便,容易出现半个汉字的情况。而后者是双字节方式,方便处理双字节字符。

    Windows NT的所有与字符有关的函数都提供两种方式的版本,而Windows9x只支持ANSI方式。_T一般同字常数相关,如_T("Hello")。如果你编译一个程序为ANSI方式,_T实际不起任何作用。而如果编译一个程序为UNICODE方式,则编译器会把"Hello"字符串以UNICODE方式保存。_TL的区别在于,不管你是以什么方式编译,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是非常有意思的一个符号(TCHARLPCTSTRLPTSTR_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)是一种被鼓励的做法。LPWSTRLPCWSTR由此产生,它们的含义类似于LPSTRLPCSTR,只是字符数据是16位的wchar_t而不是char

    然后为了实现两种编码的通用,提出了TCHAR的定义:

    如果定义_UNICODE,声明如下:typedef wchar_t TCHAR;

    如果没有定义_UNICODE,则声明如下:typedef char TCHAR;

    LPTSTRLPCTSTR中的含义就是每个字符是这样的TCHAR

    CString类中的字符就是被声明为TCHAR类型的,它提供了一个封装好的类供用户方便地使用。

    2. LPSTRLPCSTRLPTSTRLPCTSTR之间的转换:

    2.1 如何理解LPCTSTR类型?

    L表示long,这是为了兼容Windows 3.116位操作系统遗留下来的,在win32中以及其他的32为操作系统中,longnearfar修饰符都是为了兼容的作用。没有实际意义。

    P表示这是一个指针。

    C表示是一个常量。

    T表示在Win32环境中,有一个_T宏,这个宏用来表示你的字符是否使用UNICODE, 如果你的程序定义了UNICODE或者其他相关的宏,那么这个字符或者字符串将被作为UNICODE字符串,否则就是标准的ANSI字符串。

    STR表示这个变量是一个字符串。

    LPCTSTR就表示一个指向常固定地址的可以根据一些宏定义改变语义的字符 串。同样, LPCSTR就只能是一个ANSI字符串,在程序中我们大部分时间要使用带T的类型定义。LPCTSTR等价于const TCHAR *

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

    2.2 LPCTSTRCStringLPTSTR的比较

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

    由于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; //stringCString类对象

    首先,先将CString类对象转换为LPCTSTR型变量,然后再强制转换为LPSTR型变量。但是这是一种不安全的使用方法。 


    转自http://www.cnblogs.com/tekson/archive/2009/07/09/1519687.html



  • 相关阅读:
    java中的异常类
    Mysql--JDBC的基础
    eclipse使用断言
    idea中使用断言
    java的null
    array,集合(collection),集合(list)的区别
    命名管道FIFO
    标准库中的管道操作
    现代进程间的通信方式--管道
    广播编程之发送者
  • 原文地址:https://www.cnblogs.com/chinasasu/p/1715675.html
Copyright © 2011-2022 走看看