LPTSTR、LPCSTR、LPCTSTR、LPSTR的区别

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*,这样你就可以重定义一个宏进行不同字符集的转换了。
LPTSTR、LPCSTR、LPCTSTR、LPSTR的意义:
LPSTR:32bit指针 指向一个字符串,每个字符占1字节
LPCSTR:32-bit指针 指向一个常字符串,每个字符占1字节
LPCTSTR:32-bit指针 指向一个常字符串,每字符可能占1字节或2字节,取决于Unicode是否定义
LPTSTR:32-bit指针 每字符可能占1字节或2字节,取决于Unicode是否定义
Windows使用两种字符集ANSI和UNICODE,前者就是通常使用的单字节方式,但这种方式处理象中文这样的双字节字符不方便,容易出现半个汉字的情况。而后者是双字节方式,方便处理双字节字符。
WindowsNT的所有与字符有关的函数都提供两种方式的版本,而Windows9x只支持ANSI方式。_T一般同字常数相关,如_T("Hello"。如果你编译一个程序为ANSI方式,_T实际不起任何作用。而如果编译一个程序为UNICODE方式,则编译器会把"Hello"字符串以UNICODE方式保存。_T和_L的区别在于,_L不管你是以什么方式编译,一律UNICODE方式保存.
Windows核心编程的第一章。
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编译条件下都是正确编译的。
而且MS推荐你使用相匹配的字符串函数。比如处理LPTSTR或者LPCTSTR 的时候,不要用strlen ,而是要用_tcslen,否则在UNICODE的编译条件下,strlen不能处理 wchar_t*的字符串。
T是非常有意思的一个符号(TCHAR、LPCTSTR、LPTSTR、_T()、_TEXT()...),它表示使用一种中间类型,既不明确表示使用 MBCS,也不明确表示使用 UNICODE。那到底使用哪种字符集?编译的时候才决定
在vc++中有着各种字符串的表示法,如您所说。        
首先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类型的,它提供了一个封装好的类供用户方便地使用。
如果您还需要进一步的信息,请参看http://msdn.microsoft.com/library/default.asp?_url=/library/en-us/vclib/html/_crt_data_type_mappings.asp等其他有关信息。
LPTSTR、LPCSTR、LPCTSTR、LPSTR之间的转换:
如何理解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 *
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函数。
CString 转LPCTSTR:
CString cStr;
const char *lpctStr=(LPCTSTR)cStr;
LPCTSTR转CString:
LPCTSTR lpctStr;
CString cStr=lpctStr;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/510021.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Hbase快照Snapshot 数据备份、恢复与迁移

场景 hbase数据迁移时我们需要统计迁移时的数据量,以确保迁移后的数据的完成,但是如果hbase表数据持续增加的话,迁移时无法统计出准确的数据量,此时我们使用快照的方式进行数据迁移,以确保迁移的数量可以和某一时间节点…

多线程Thread类创建多线程

package com.ajax; //多线程Thread类创建多线程 public class Example02 {public static void main(String[] args){new MyThread().start();new MyThread().start();new MyThread().start();//创建一个线程对象并开启new MyThread().start();} } class MyThread extends Threa…

C++面试题一

指针和引用的区别指针指向一块内存,它的内容是指向内存的地址;引用是某内存的别名 引用使用是无需解引用,指针需解引用 引用不能为空,指针可以为空 引用在定义是被初始化一次,之后不可变;指针可变 程序…

maven 打包报错 surefire-reports for the individual test results.

Eclipse Maven打包报错 [ERROR] [ERROR] Please refer to D:\File\workspace\izh-common-util\target\surefire-reports for the individual test results. [ERROR] -> [Help 1] [ERROR] 原因这是因为测试代码时遇到错误,它会停止编译。 解决方法 在pom.xm…

ubuntu 配置 静态ip

1.参看网卡名称 ifconfig lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0inet6 addr: ::1/128 Scope:HostUP LOOPBACK RUNNING MTU:65536 Metric:1RX packets:10210 errors:0 dropped:0 overruns:0 frame:0TX packets:10210 errors:0 dropped:…

eclipse maven项目 maven build 提示jdk版本不对

eclipse打包maven项目提示jdk版本不对&#xff0c;但eclipse版本已经修改jdk版本&#xff0c;可查看maven配置是否正确 maven项目中pom.xml 添加 <build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven…

WSAAsyncSelect模型

WSAAsyncSelect模型允许应用程序以Windows消息的方式接收网络事件通知。许多对性能要求不高的网络应用程序都采用WSAAsyncSelect模型&#xff0c;MFC的CSocket类也使用了它。 WSAAsyncSelect自动把套接字设为非阻塞模式&#xff0c;并且为套接字绑定一个窗口句柄&#xff0c;当…

计算图像的直方图,求峰值点

程序步骤&#xff1a; 1.输入图像 2.灰度化 3.计算直方图 4.求峰值点 #include "../LaneDetecte_SRC/detector_lane.hpp" #include "../common_src/unity.hpp" #include "../common_src/common_func.hpp" #include <chrono> #include…

线程休眠

package com.ajax; //线程休眠&#xff1a;该方法可以让当前正在执行的线程暂停一段时间&#xff0c;进入休眠等待状态让其他线程可以执行 public class Example04 {public static void main(String[] args) throws Exception{new Thread(new SleepThread()).start();for(int i…

HUE 打开 WorkFlow异常 Operation category READ is not supported in state standby

异常&#xff1a;在hue上配置的一些定时任务突然停止执行。 1.打开页面HUE->WorkFlow 发现页面异常&#xff0c;无法进入WorkFlow&#xff0c;如下图 2.查看HUE日志 查看到WebHdfsException异常&#xff0c;访问HDFS文件浏览器报错&#xff0c; [26/Jun/2019 09:29:55 080…

失败的面试经历

最近感觉在这家公司实在是干不下去了。于是就投简历面试吧。想要找到下家&#xff0c;首先是要写好自己的简历&#xff0c;于是呼&#xff0c;想想自己这几年干过的东西&#xff0c;呼拉一下全写上去了。然后就在招聘网站上逢C/C职位就投。于是就等来了不少面试机会&#xff0c…

opencv 常用操作 c++

图像水平垂直方向拼接: cv::vconcat&#xff08;B,C&#xff0c;A&#xff09;; // 等同于A[B ;C] cv::hconcat&#xff08;B,C&#xff0c;A&#xff09;; // 等同于A[B C] 初始化Mat: cv::Mat edgeDest(cv::Size(10,10), CV_8UC1, cv::Scalar(0)); double a[3][3] { 0.…

hdfs fsck命令查看HDFS文件对应的文件块信息(Block)和位置信息(Locations)

关键字&#xff1a;hdfs fsck、block、locations 在HDFS中&#xff0c;提供了fsck命令&#xff0c;用于检查HDFS上文件和目录的健康状态、获取文件的block信息和位置信息等。 fsck命令必须由HDFS超级用户来执行&#xff0c;普通用户无权限。 [hadoopdev ~]$ hdfs fsck Usage…

线程让步

package com.ajax; //线程让步&#xff1a;通过yield方法来实现&#xff0c;该方法和sleep方法有点相似&#xff0c;都可以让当前正在运行的线程暂停&#xff0c;区别在于yield方法不会阻塞该线程&#xff0c;他只是将线程转换为就绪状态&#xff0c;让系统的调度器 //重新调度…

tcp连接超时处理

设置connect超时很简单&#xff0c;CSDN上也有人提到过使用select&#xff0c;但却没有一个令人满意与完整的答案。偶所讲的也正是select函数&#xff0c;此函数集成在winsock1.1中&#xff0c;简单点讲&#xff0c;"作用使那些想避免在套接字调用过程中被锁定的应用程序&…

Hbase Native memory allocation (mmap) failed to map xxx bytes for committing reserved memory

新启动测试环境Hbase报错&#xff0c;报错日志如下 # # There is insufficient memory for the Java Runtime Environment to continue. # Native memory allocation (mmap) failed to map 31715688448 bytes for committing reserved memory. # An error report file with mo…

Tcp设置发送和接收超时

linux和windows下用setsockopt设置SO_SNDTIMEO,SO_RCVTIMEO的参数的一点区别 UDP的socket在某些情况&#xff1a;如对方关闭时&#xff0c;本地可能sendto不出去数据&#xff0c;然后recvfrom就会被阻塞&#xff0c;这时就需要设置 这两个参数的值提高程序质量。 linux: …

线程插队

package com.ajax; //线程插队 public class Example06 {public static void main(String[] args)throws Exception{Thread tnew Thread(new EmergencyThread(),"线程一");t.start();for(int i0;i<6;i){System.out.println(Thread.currentThread().getName()"…

txt记录位置 c++,python显示位置

///c 写/ std::ofstream lane_postion_log(ROOT_DIR"/build/lane_position_log.txt");//创建文件 lane_postion_log <<p.x<<","<<p.y<<","<<p.z<<endl;//写位置 lane_postion_log.close(); //python显示…

CDH Yarn资源动态分配 - 指定资源限制 公平调度具体设置

日常工作中会涉及到各种资源分配等问题&#xff0c;跨部门&#xff0c;跨业务等等&#xff0c;这里介绍基于CDH版本的Yarn 公平调度&#xff08;实际使用DRF调度&#xff09; 不同时间配置不同资源参考&#xff08;计划模式&#xff09;&#xff1a;https://datamining.blog.cs…