LPCSTR,LPCTSTR和LPTSTR


109

什么区别LPCSTRLPCTSTRLPTSTR

为什么我们需要这样做将字符串转换为LV/ _ITEM结构变量pszText

LV_DISPINFO dispinfo;  
dispinfo.item.pszText = LPTSTR((LPCTSTR)string);

2
您能否确切地说出“字符串”是什么类型?(例如CString)
约翰·西伯里

Answers:


122

要回答问题的第一部分:

LPCSTR是指向const字符串的指针(LP表示Long Pointer

LPCTSTR是指向const TCHAR字符串的指针(TCHAR是宽字符还是char,取决于项目中是否定义了UNICODE)

LPTSTR是指向(非常量)TCHAR字符串的指针

实际上,在过去谈论这些时,为简单起见,我们省略了“指向某个单词的指针”一词,但是正如“轻度赛道”所提到的,它们都是指针。

这是一篇很棒的codeproject文章,描述了C ++字符串(请参阅2/3,了解不同类型的图表)


18
都错了 这些东西都不是字符串。它们都是指针。-1
Lightness Races in Orbit

8
@LightnessRacesinOrbit您在技术上是正确的-尽管根据我的经验,在C ++中引用字符串类型时,为了简洁起见,通常省略“指向...的指针”的描述
John SABLE15,2015年

2
@JohnSably:在C中,是的。在C ++中,绝对不应该!
Lightness Races in Orbit 2015年

4
请注意,该codeproject文章是15年前写的,除非对其进行更新,否则包含有关Unicode字符始终为2个字节的误导性假设。那是完全错误的。甚至UTF16都是可变长度的……最好说宽字符是UCS-2编码的,在这种情况下,“ Unicode”是指UCS-2。
u8it

1
嗯...在这种情况下,@ LightnessRacesinOrbit,我要添加一个附录,在C ++中引用C字符串时可以省略“指向...的指针”。 (已衰减)字符串文字,或者与使用C语言编写的代码进行连接/交互时,它们依赖于C类型而不是C ++类型,并且/或者具有通过C进行链接extern "C"。是的,除此之外,它肯定应该需要“指针”位或特定的C字符串描述。
贾斯汀时间-恢复莫妮卡

87

快速而肮脏:

LP== 大号P ointer。只考虑指针或char *

C= C onst,在这种情况下,我认为它们表示字符串是const,而不是指针是const。

STR字符串

T根据编译选项,它适用于宽字符或char(TCHAR)。


16
T不是宽字符,而是各种字符类型。W表示宽(如WCHAR)。如果定义了UNICODE,则TCHAR == WCHAR,否则TCHAR == CHAR。因此,如果未定义UNICODE,则LPCTSTR == LPCSTR。
jalf

10
这就是为什么我写了“取决于编译选项”的原因
蒂姆,

14
我真的很喜欢这种解释:)。非常感谢
Dzung Nguyen 2010年

@jalf,那么T代表什么?
Pacerier


36

8位AnsiStrings

  • char:8位字符-基础C / C ++数据类型
  • CHARchar-Windows数据类型的别名
  • LPSTRL ong p ointer)的以 null终止的字符串CHAR
  • LPCSTRL ong P ointer)的以空值结尾的常量字符串CHAR

16位UnicodeStrings

  • wchar_t:16位字符-底层C / C ++数据类型
  • WCHARwchar_t-Windows数据类型的别名
  • LPWSTRL ong p ointer)的以 null终止的字符串WCHAR
  • LPCWSTRL ong P ointer)的以空值结尾的常量字符串WCHAR

取决于UNICODE定义

  • TCHARWCHAR是否定义了UNICODE的别名;除此以外CHAR
  • LPTSTRL ong p ointer)的以 null终止的字符串TCHAR
  • LPCTSTRL ong P ointer)的以空值结尾的常量字符串TCHAR

所以

| Item              | 8-bit        | 16-bit      | Varies          |
|-------------------|--------------|-------------|-----------------|
| character         | CHAR         | WCHAR       | TCHAR           |
| string            | LPSTR        | LPWSTR      | LPTSTR          |
| string (const)    | LPCSTR       | LPCWSTR     | LPCTSTR         |

奖励阅读

TCHAR文字字符 archive.is


4
可耻的是,这个答案永远不会登上榜首,因为它太新了……这确实是需要解决的问题。到目前为止,这是最好的答案。
Dan Bechard '18

当我在工作中进行Unicode项目时,这确实对我有很大帮助。谢谢!
Yoon5oo

好答案。我认为值得补充的是,Unicode版本使用UTF16,因此每个16位块不是字符而是代码单元。名称是历史名称(当Unicode === UCS2时)。
玛格丽特·布鲁姆

5

添加到约翰和蒂姆的答案。

除非您为Win98编码,否则应在应用程序中使用6+字符串类型中的只有两种

  • LPWSTR
  • LPCWSTR

其余部分旨在支持ANSI平台或双重编译。今天,它们已经不像以前那样重要了。


2
@BlueRaja,我主要在回答中指的是基于C的字符串。但是对于C ++,我会避免使用std::string它,因为它仍然是基于ASCII的字符串,因此更喜欢std::wstring使用。
JaredPar

1
除非直接调用函数的ASCII(* A)或widechar(* W)版本,否则应使用LPTSTR和LPCTSTR。它们是您在编译时指定的任何字符宽度的别名。
osvein

...并且现在,Microsoft正在努力使*AWinAPI版本与UTF-8代码页兼容,因此它们之间的联系突然变得更加相关。; P
贾斯汀时间-恢复莫妮卡

4

要回答问题的第二部分,您需要执行以下操作

LV_DISPINFO dispinfo;  
dispinfo.item.pszText = LPTSTR((LPCTSTR)string);

因为MS的LVITEM结构具有一个LPTSTR(即可变的 T字符串指针)而不是一个LPCTSTR。你在做什么

1)将string(a CString猜测)转换为LPCTSTR(实际上意味着将其字符缓冲区的地址作为只读指针获取)

2)通过const舍弃其-ness 将该只读指针转换为可写指针。

这取决于所dispinfo使用的内容是否使您的ListView呼叫最终有机会尝试通过它进行写操作pszText。如果这样做的话,这可能是一件非常不好的事情:毕竟给了您一个只读指针,然后决定将其视为可写的:也许是有原因的,它是只读的!

如果是CString,则可以选择使用string.GetBuffer()-故意为您提供可写内容LPTSTR。然后,您必须记住ReleaseBuffer()如果字符串确实发生更改,则要调用。或者,您可以分配一个本地临时缓冲区,然后将字符串复制到其中。

99%的时间这是不必要的,并且将其LPCTSTR作为LPTSTR工作是可行的……但是有一天,当您最不希望这样做时……


1
您应避免使用C样式强制转换,xxx_cast<>()而应改用。
哈珀

@harper你说的很对-但是我引用了OP,这就是他要的代码。如果我自己编写代码,那么肯定会使用xxx_cast<>而不是混合两种基于括号的转换样式!
AAT
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.