LPCSTR, LPCTSTR e LPTSTR


109

Quale la differenza tra LPCSTR, LPCTSTRe LPTSTR?

Perché è necessario farlo per convertire una stringa in una variabile di struttura LV/ : _ITEMpszText

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

2
Potresti dire esattamente che tipo è "stringa"? (ad esempio CString)
John Sibly

Risposte:


122

Per rispondere alla prima parte della tua domanda:

LPCSTRè un puntatore a una stringa const (LP significa Long Pointer )

LPCTSTRè un puntatore a una const TCHARstringa, ( TCHARessendo un carattere ampio o un carattere a seconda che UNICODE sia definito nel progetto)

LPTSTRè un puntatore a una TCHARstringa (non const)

In pratica, parlando di questi in passato, abbiamo tralasciato la frase "pointer to a" per semplicità, ma come accennato da lightness-race-in-orbit sono tutti indicatori.

Questo è un ottimo articolo sul progetto di codice che descrive le stringhe C ++ (vedi 2/3 fino in fondo per un grafico che confronta i diversi tipi)


18
Tutto sbagliato. Nessuna di queste cose sono stringhe. Sono tutti indicatori. -1
Gare di leggerezza in orbita

8
@LightnessRacesinOrbit Sei tecnicamente corretto - anche se nella mia esperienza è pratica comune tralasciare la descrizione "pointer to a ...." per brevità quando si fa riferimento a tipi di stringa in C ++
John Sibly,

2
@ JohnSibly: In C, sì. In C ++, non dovrebbe assolutamente esserlo !!
Gare di leggerezza in orbita il

4
Si noti che l'articolo di codeproject è stato scritto 15 anni fa e, a meno che non venga aggiornato, contiene ipotesi fuorvianti sul fatto che i caratteri Unicode siano sempre 2 byte. È completamente sbagliato. Anche UTF16 è di lunghezza variabile ... è molto meglio dire che i caratteri larghi sono codificati UCS-2 e che "Unicode" in questo contesto si riferisce a UCS-2.
u8it

1
Hmm ... in questo caso, @LightnessRacesinOrbit, aggiungerei un addendum che va bene omettere il "puntatore a ..." quando si fa riferimento alle stringhe C in C ++, if-and-only-if riferito specificamente a letterali stringa (decaduti) o quando si interfaccia / si lavora con codice scritto in C, si basa su tipi C anziché tipi C ++ e / o ha un collegamento C tramite extern "C". A parte questo, sì, dovrebbe sicuramente aver bisogno del bit "pointer" o di una descrizione specifica come stringa C.
Justin Time - Ripristina Monica l'

87

Veloce e sporco:

LP== L ong P ointer. Pensa solo a pointer o char *

C= C onst, in questo caso, penso che significhino che la stringa di caratteri è una const, non il puntatore che è const.

STRè una stringa

la Tè per una vasta carattere o char (TCHAR) a seconda delle opzioni di compilazione.


16
T non è per carattere ampio, è per tipo di carattere variabile. W sta per wide (come in WCHAR). Se UNICODE è definito, TCHAR == WCHAR, altrimenti TCHAR == CHAR. Quindi, se UNICODE non è definito, LPCTSTR == LPCSTR.
jalf

10
ecco perché ho scritto "a seconda delle opzioni di compilazione"
Tim

14
Adoro questo tipo di spiegazioni :). Grazie mille
Dzung Nguyen

@jalf, quindi cosa significa T?
Pacerier


36

AnsiStrings a 8 bit

  • char: Carattere a 8 bit - tipo di dati C / C ++ sottostante
  • CHAR: alias di char- Tipo di dati Windows
  • LPSTR: stringa con terminazione null di CHAR ( L ong P ointer)
  • LPCSTR: stringa costante con terminazione null di CHAR ( L ong P ointer)

UnicodeStrings a 16 bit

  • wchar_t: Carattere a 16 bit - tipo di dati C / C ++ sottostante
  • WCHAR: alias di wchar_t- Tipo di dati Windows
  • LPWSTR: stringa con terminazione null di WCHAR ( L ong P ointer)
  • LPCWSTR: stringa costante con terminazione null di WCHAR ( L ong P ointer)

a seconda di UNICODEdefinire

  • TCHAR: alias di WCHARse UNICODE è definito; altrimentiCHAR
  • LPTSTR: stringa con terminazione null di TCHAR ( L ong P ointer)
  • LPCTSTR: stringa costante con terminazione null di TCHAR ( L ong P ointer)

Così

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

Lettura bonus

TCHARCarattere testo ( archive.is )


4
Peccato che questa risposta non raggiungerà mai la cima perché è così nuova .. è davvero qualcosa che COSÌ deve risolvere. Questa è di gran lunga la migliore risposta.
Dan Bechard

Questo mi aiuta davvero molto mentre sto lavorando al progetto Unicode. Grazie!
Yoon5oo

Bella risposta. Penso che valga la pena aggiungere che la versione Unicode utilizza UTF16, quindi ogni blocco a 16 bit non è un carattere ma un'unità di codice. I nomi sono storici (quando Unicode === UCS2).
Margaret Bloom,

5

In aggiunta alla risposta di John e Tim.

A meno che tu non stia codificando per Win98, ci sono solo due dei 6+ tipi di stringhe che dovresti usare nella tua applicazione

  • LPWSTR
  • LPCWSTR

Il resto ha lo scopo di supportare piattaforme ANSI o compilazioni doppie. Quelle non sono più rilevanti oggi come una volta.


2
@BlueRaja, mi riferivo principalmente alle stringhe basate su C nella mia risposta. Ma per C ++ eviterei std::stringperché è ancora una stringa basata su ASCII e preferisco std::wstringinvece.
JaredPar

1
Dovresti usare LPTSTR e LPCTSTR a meno che tu non chiami direttamente le versioni ASCII (* A) o widechar (* W) delle funzioni. Sono alias di qualsiasi larghezza di carattere specificata durante la compilazione.
osvein

... E ora che Microsoft sta lavorando per rendere le *Aversioni di WinAPI compatibili con la code page UTF-8, sono improvvisamente molto più rilevanti. ; P
Justin Time - Ripristina Monica il

4

Per rispondere alla seconda parte della tua domanda, devi fare cose come

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

perché MS LVITEMstruttura ha una LPTSTR, cioè un mutevole puntatore T-stringa, non un LPCTSTR. Quello che stai facendo è

1) converti string( CStringa indovinare) in an LPCTSTR(che in pratica significa ottenere l'indirizzo del suo buffer di caratteri come puntatore di sola lettura)

2) converti quel puntatore di sola lettura in un puntatore scrivibile gettando via la sua const-ness.

Dipende da cosa dispinfoviene utilizzato se c'è o meno la possibilità che la tua ListViewchiamata finisca per provare a scrivere attraverso quello pszText. Se lo fa, questa è una cosa potenzialmente molto negativa: dopotutto ti è stato dato un puntatore di sola lettura e poi hai deciso di trattarlo come scrivibile: forse c'è una ragione per cui era di sola lettura!

Se è un con CStringcui stai lavorando, hai la possibilità di usare string.GetBuffer()- questo ti dà deliberatamente un scrivibile LPTSTR. Devi quindi ricordarti di chiamare ReleaseBuffer()se la stringa viene modificata. Oppure puoi allocare un buffer temporaneo locale e copiare la stringa al suo interno.

Il 99% delle volte non sarà necessario e trattarlo LPCTSTRcome un LPTSTRlavoro ... ma un giorno, quando meno te lo aspetti ...


1
Dovresti evitare il cast in stile C e usare xxx_cast<>()invece.
Harper

@harper Hai ragione - ma stavo citando l'OP, questo è il codice di cui stava chiedendo. Se avessi scritto il codice da solo, avrei sicuramente usato xxx_cast<>piuttosto che mescolare due diversi stili di casting basati su parentesi!
AAT
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.