关于LPSTR、LPCSTR 和 LPTSTR、LPCTSTR和CString

呀呀的呀 2010-05-14 03:40:23
void fun(CString &strTempPath)
{
GetTempPath(_MAX_PATH, (LPTSTR)(LPCTSTR)strTempPath); //得到系统temp文件夹目录
if (strTempPath.IsEmpty()) return;

//判断目录是否以反斜杠结尾
int nPos = strTempPath.ReverseFind(TCHAR('\\'));
//加入反斜杠
if (-1 == nPos || nPos != strTempPath.GetLength()-1)
strTempPath+= _T("\\");
}

为啥执行完GetTempPath(_MAX_PATH, (LPTSTR)(LPCTSTR)strTempPath);的时候strTempPath是有值的,
但是if (strTempPath.IsEmpty()) return;这边它又会退出呢?

补充下:GetTempPath(DWORD..., LPTSTR...)这个API函数的第二个参数是LPTSTR类型的

该如何做呢?
一定要
char csTempPath[_MAX_PATH];
GetTempPath(_MAX_PATH, csTempPath);
strTempPath.Format(_T("%s"), csTempPath);
这样写吗?
有没有其它的方法可以直接使用strTempPath这个变量操作的


哪位大哥知道的告诉我下,谢谢
如果可以的话把CString的以它们之间的转换也贴给我,谢谢
...全文
509 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
finder_zhang 真热心。厉害就不必再说了。谢谢。
呀呀的呀 2010-05-16
  • 打赏
  • 举报
回复
感谢 finder_zhang
heword999 2010-05-16
  • 打赏
  • 举报
回复
友情帮顶...
FireBurn 2010-05-15
  • 打赏
  • 举报
回复
finder_zhang的解释真是详尽细致,厉害。
finder_zhang 2010-05-14
  • 打赏
  • 举报
回复
该如何做呢?
一定要
char csTempPath[_MAX_PATH];
GetTempPath(_MAX_PATH, csTempPath);
strTempPath.Format(_T("%s"), csTempPath);
这样写吗?
有没有其它的方法可以直接使用strTempPath这个变量操作的

可以的,CString的设计者很厉害,很多以前用字符串(字符数组)去做的工作,现在都可以用CString来代劳,但我们一定要理解工作原理.

CString strTempPath;

GetTempPath(_MAX_PATH,strTempPath.GetBuffer(_MAX_PATH));
strTempPath.ReleaseBuffer();
if (strTempPath.IsEmpty())
{
}

这样就行了,原理是这样的.
strTempPath.GetBuffer(_MAX_PATH) 这个与之前的 (LPTSTR)(LPCTSTR)strTempPath 一样,传进去的是 m_pchData ,但他有什么不同呢?
他还改写了CString的使用计数,改为1了,然后还为这个字符串分配了_MAX_PATH 长度的堆空间,来准备放东西的.还把堆的大小记了下来,是260.如果查内存的话,可以查到 m_pchData 前面的内容是 1 0 0x104(260)

但是操作完之后,要再执行ReleaseBuffer(),这个MSDN有说,他的内部动作是按照我们真正读写进堆的字符串内容,求出长度,再写回去前面为0的长度的地方.
所以MSDN会告诉我们,GetBuffer后如果有改写字符串的话,一定要调用ReleaseBuffer,否则,字符长度等信息,就极可能跟我们实现的内容不同步了.
finder_zhang 2010-05-14
  • 打赏
  • 举报
回复
IsEmpty 函数只查看前面的长度值,也就是 字符串前面的 "a" 的地址再向前的地方,这个时候该值为0,因为是新的,而再前面的使用记数是 -1 ,尽管后面写入了内容.

所以IsEmpty 还是认为是空的.
finder_zhang 2010-05-14
  • 打赏
  • 举报
回复
为啥执行完GetTempPath(_MAX_PATH, (LPTSTR)(LPCTSTR)strTempPath);的时候strTempPath是有值的,
但是if (strTempPath.IsEmpty()) return;这边它又会退出呢?

回1楼,原理是这样的,CString里面只有一个变量,就是 m_pchData ,是指向堆中字符串的指针,而该指针地址的前面,放的是三个变量,分别是CString的使用计数,字符长度,已分配的长度.
例如CString str = "abc"; ,这时m_pchData 指向了字符 a 的地址,而a前面的内存的内容为1 3 3,因为长度是3.

GetTempPath(_MAX_PATH, (LPTSTR)(LPCTSTR)strTempPath);
这句传进去的 (LPTSTR)(LPCTSTR)strTempPath 其实就是把 m_pchData 放入去,只是简单地把数据放到了堆中.
但是前面的使用计数,长度,已分配长度,均未改写.

楼主可以查一下内存,就可以看到的了.

CString本来提供的 LPCTSTR 的转换,是方便我们取其字符串,他本来提供的是 LP 'C' TSTR ,意味着这是一个常量,不希望用户去改写他,但我们真的这样硬改成非常量而改写了,问题就出来了,因为前面的长度等信息并未改写.
jyh_baoding 2010-05-14
  • 打赏
  • 举报
回复
看看他们的定义
社会栋梁 2010-05-14
  • 打赏
  • 举报
回复
http://blog.ednchina.com/wzhenhua/357260/Message.aspx
http://blog.sina.com.cn/s/blog_4942b965010007fi.html?retcode=0
wuweiyin 2010-05-14
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 liwei3290 的回复:]
一、BSTR、LPSTR和LPWSTR
   在Visual C++.NET的所有编程方式中,我们常常要用到这样的一些基本字符串类型,如BSTR、LPSTR和LPWSTR等。之所以出现类似上述的这些数据类型,是因为不同编程语言之间的数据交换以及对ANSI、Unicode和多字节字符集(MBCS)的支持。
  那么什么是BSTR、LPSTR以及LPWSTR呢?
  BSTR(Basic ST……
[/Quote]
学习了。
社会栋梁 2010-05-14
  • 打赏
  • 举报
回复
LPSTR、LPCSTR、LPTSTR、LPCTSTR的来源及意义
UNICODE:它是用两个字节表示一个字符的方法。比如字符'A'在ASCII下面是一个字节,可'A'在UNICODE下面是两个字节,高字节用0填充,而且汉字'程'在ASCII下面是两个字节,而在UNICODE下仍旧是两个字节。UNICODE的用处就是定长表示世界文字,据统计,用两个字节可以编码现存的所有文字而没有二义。

LPSTR、LPCSTR、LPTSTR、LPCTSTR 及 LPWSTR、LPCWSTR 的意义:

LPSTR: 32bit指针 指向一个字符串,每个字符占1字节。 相当于 char *

LPCSTR: 32-bit指针 指向一个常字符串,每个字符占1字节。 相当于 const char *

LPTSTR: 32-bit指针 每字符可能占1字节或2字节,取决于Unicode是否定义

LPCTSTR:32-bit指针 指向一个常字符串,每字符可能占1字节或2字节,取决于Unicode是否定义

LPWSTR: 32-bit指针,指向一个unicode字符串的指针,每个字符占2字节。 
LPCWSTR:32-bit指针, 指向一个unicode字符串常量的指针,每个字符占2字节。 

在上面的类型中,L表示long, P表示指针,C表示constant, T表示指针指向的字符占的字节数取决于Unicode是否定义,W表示wide,STR就是string的意思

LPSTR = char *
LPCSTR = const char *

LPTSTR = _TCHAR * (或 TCHAR *)
LPCTSTR = const _TCHAR * (或 const TCHAR *)

LPWSTR = wchar_t *
LPCWSTR = const wchar_t *

_T是一个适配的宏


#ifdef _UNICODE
_T就是L
#else

_T就是ANSI的。

Windows使用两种字符集ANSI和UNICODE,前者就是通常使用的单字节方式,但这种方式处理象中文这样的双字节字符不方便,容易出现半个汉字的情况。而后者是双字节方式,方便处理双字节字符。WindowsNT 的所有与字符有关的函数都提供两种方式的版本,而Windows9x只支持ANSI方式。_T一般同字符串常数相关,如_T("Hello")。如果你编译一个程序为ANSI方式,_T实际不起任何作用。而如果编译一个程序为UNICODE方式,则编译器会把"Hello"字符串以UNICODE方式保存。_T 和L的区别在于,对于L, 不管你是以什么方式编译,一律UNICODE方式保存. 

比如:
wchar_t str[] = L"Hello World!"; 这个就是双子节存储字符了,wchar_t str[] 表示定义一个以双字节存储字符的字符数组。

赋值式左右两边必须匹配。

所以从兼容性和扩展性考虑,最好的方法是: TCHAR str[] = _T("Hello World!");


LPTSTR lpStr = new TCHAR[32];
TCHAR* szBuf = _T("Hello");
以上两句使得无论是在UNICODE编译条件下都是正确编译的。



MS推荐你使用相匹配的字符串函数。
比如处理LPTSTR或者LPCTSTR 的时候,不要用strlen ,而是要用_tcslen

否则在UNICODE的编译条件下,strlen不能处理 wchar_t*的字符串。


注意L 和 _T 的使用方法。

LPTSTR, LPCTSTR, 及_T(常量字符串) 受_T 影响。

介绍字符串类型:char, wchar_t, TCHAR, CHAR, WCHAR.

TCHAR 的定义:

#ifdef UNICODE
typedef wchar_t TCHAR;

#else
typedef unsigned char TCHAR;

#endif


typedef unsigned char CHAR;
typedef unsigned wchar_t WCHAR;

由此可以看出,unsigned char 和 wchar_t 都是基本数据类型, CHAR实施上就是unsigned char, WCHAR为wchar_t ,而TCHAR根据是否支持unicode而不同。

在程序中,可以用的名称有5种,unsigned char(CHAR), wchar_t(WCHAR), TCHAR, 但为了扩展性和兼容性,推荐使用TCHAR.
liwei3290 2010-05-14
  • 打赏
  • 举报
回复
一、BSTR、LPSTR和LPWSTR
   在Visual C++.NET的所有编程方式中,我们常常要用到这样的一些基本字符串类型,如BSTR、LPSTR和LPWSTR等。之所以出现类似上述的这些数据类型,是因为不同编程语言之间的数据交换以及对ANSI、Unicode和多字节字符集(MBCS)的支持。
  那么什么是BSTR、LPSTR以及LPWSTR呢?
  BSTR(Basic STRing,Basic字符串)是一个OLECHAR*类型的Unicode字符串。它被描述成一个与自动化相兼容的类型。由于操作系统提供相应的API函数(如SysAllocString)来管理它以及一些默认的调度代码,因此BSTR实际上就是一个COM字符串,但它却在自动化技术以外的多种场合下得到广泛使用。图1描述了BSTR的结构,其中DWORD值是字符串中实际所占用的字节数,且它的值是字符串中Unicode字符的两倍。
  LPSTR和LPWSTR是Win32和VC++所使用的一种字符串数据类型。LPSTR被定义成是一个指向以NULL(‘\0’)结尾的8位ANSI字符数组指针,而LPWSTR是一个指向以NULL结尾的16位双字节字符数组指针。在VC++中,还有类似的字符串类型,如LPTSTR、LPCTSTR等,它们的含义如图2所示。
  例如,LPCTSTR是指“long pointer to a constant generic string”,表示“一个指向一般字符串常量的长指针类型”,与C/C++的const char*相映射,而LPTSTR映射为 char*。
  一般地,还有下列类型定义:
#ifdef UNICODE
  typedef LPWSTR LPTSTR;
  typedef LPCWSTR LPCTSTR;
#else
  typedef LPSTR LPTSTR;
  typedef LPCSTR LPCTSTR;
#endif

16,550

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Creator Browser
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧