Wat is het verschil tussen LPCSTR
, LPCTSTR
en LPTSTR
?
Waarom moeten we dit doen om een string om te zetten in een LV
/ _ITEM
structuurvariabele pszText
:
LV_DISPINFO dispinfo;
dispinfo.item.pszText = LPTSTR((LPCTSTR)string);
Antwoord 1, autoriteit 100%
Om het eerste deel van uw vraag te beantwoorden:
LPCSTR
is een verwijzing naar een const-tekenreeks (LP betekent Lang Aanwijzer)
LPCTSTR
is een verwijzing naar een const TCHAR
-tekenreeks, (TCHAR
is ofwel een brede char of char, afhankelijk van of UNICODE is gedefinieerd in uw project)
LPTSTR
is een verwijzing naar een (niet-const) TCHAR
-tekenreeks
In de praktijk hebben we, als we hier in het verleden over spraken, de term ‘aanwijzer naar een’ voor de eenvoud weggelaten, maar zoals vermeld door lightness-races-in-orbit zijn het allemaal wijzers.
Dit is een geweldig codeproject-artikeldat C++-strings beschrijft (zie 2/3 de weg naar beneden voor een grafiek die de verschillende typen vergelijkt)
Antwoord 2, autoriteit 71%
Snel en vuil:
LP
== Long Pointer. Denk maar aan pointer of char*
C
= Const, in dit geval denk ik dat ze bedoelen dat de tekenreeks een const is, niet dat de aanwijzer const is.
STR
is tekenreeks
de T
is voor een breed teken of char (TCHAR), afhankelijk van de compileropties.
Bonuslezen
Van Waar staat de letter “T” in LPTSTR voor?: archief
Waar staat de letter “T” in LPTSTR voor?
17 oktober 2006
De “T” in LPTSTR komt van de “T” in TCHAR. Ik weet het niet zeker, maar het lijkt vrij waarschijnlijk dat het staat voor “tekst”. Ter vergelijking: de “W” in WCHAR komt waarschijnlijk van de C-taalstandaard, waar het staat voor “wide”.
Antwoord 3, autoriteit 41%
8-bits AnsiStrings
CHAR
: 8-bits teken (onderliggend C/C++-gegevenstype)CHAR
: alias vanCHAR
(Windows-gegevenstype)LPSTR
: null-terminated string vanCHAR
(Long Pointer)LPCSTR
: constante null-terminated string vanCHAR
(Long Pointer Conmiddellijk)
16-bits UnicodeStrings
wchar_t
: 16-bits teken (onderliggend C/C++-gegevenstype)WCHAR
: alias vanwchar_t
(Windows-gegevenstype)LPWSTR
: null-terminated string vanWCHAR
(Long Pointer)LPCWSTR
: constante null-terminated string vanWCHAR
(Long Pointer Conmiddellijk)
afhankelijk van UNICODE
definiëren
TCHAR
: alias vanWCHAR
als UNICODE is gedefinieerd; andersCHAR
LPTSTR
: null-terminated string vanTCHAR
(Long Pointer)LPCTSTR
: constante null-terminated string vanTCHAR
(Long Pointer Conmiddellijk)
Dus:
Artikel | 8-bits (Ansi) | 16-bits (Breed) | Varieert |
---|---|---|---|
karakter | CHAR |
WCHAR |
TCHAR |
tekenreeks | LPSTR |
LPWSTR |
LPTSTR |
string (const) | LPCSTR |
LPCWSTR |
LPCTSTR |
Antwoord 4, autoriteit 5%
Toevoegen aan het antwoord van John en Tim.
Tenzij u codeert voor Win98, zijn er slechts twee van de 6+ stringtypes die u in uw toepassing zou moeten gebruiken
LPWSTR
LPCWSTR
De rest is bedoeld om ANSI-platforms of dubbele compilaties te ondersteunen. Die zijn tegenwoordig niet meer zo relevant als vroeger.
Antwoord 5, autoriteit 3%
Om het tweede deel van uw vraag te beantwoorden, moet u dingen doen als
LV_DISPINFO dispinfo;
dispinfo.item.pszText = LPTSTR((LPCTSTR)string);
omdat de LVITEM
-struct van MS een LPTSTR
heeft, dwz een veranderlijkeT-string-aanwijzer, niet een LPCTSTR
. Wat je doet is
1) converteer string
(een CString
naar schatting) naar een LPCTSTR
(wat in de praktijk betekent dat je het adres van zijn karakterbuffer krijgt als alleen-lezen-aanwijzer)
2) zet die alleen-lezen-aanwijzer om in een beschrijfbare aanwijzer door zijn const
-heid weg te gooien.
Het hangt ervan af waarvoor dispinfo
wordt gebruikt of er een kans is dat uw ListView
-aanroep uiteindelijk probeert om te schrijvenvia dat pszText
. Als dit het geval is, is dit een potentieel zeer slechte zaak: u kreeg tenslotte een alleen-lezen-aanwijzer en besloot deze als beschrijfbaar te behandelen: misschien is er een reden dat het alleen-lezen was!
Als het een CString
is waarmee u werkt, heeft u de mogelijkheid om string.GetBuffer()
te gebruiken — dat geeft u opzettelijk een beschrijfbare LPTSTR
. U moet dan onthouden om ReleaseBuffer()
aan te roepen als de tekenreeks wordt gewijzigd. Of je kunt een lokale tijdelijke buffer toewijzen en de string daar naartoe kopiëren.
99% van de tijd zal dit niet nodig zijn en de LPCTSTR
behandelen als een LPTSTR
zal werken… maar op een dag, wanneer je het het minst verwacht…
Antwoord 6
Het korte antwoord op het tweede deel van de vraag is eenvoudigweg dat de klasse CString
geen directe typecast-conversie biedt door het ontwerp en wat je doet is een soort van valsspelen.
Een langer antwoord is het volgende:
De reden dat u CString
naar LPCTSTR
kunt typen, is omdat CString deze mogelijkheid biedt door operator=
te overschrijven. Door het ontwerp biedt het conversie naar alleen de LPCTSTR
-aanwijzer, zodat de tekenreekswaarde niet kan worden gewijzigd met deze aanwijzer.
Met andere woorden, het levert gewoon geen overbelasting operator=
op om de CString
om te zetten in LPSTR
om dezelfde reden als hierboven . Ze willen niet toestaan dat de tekenreekswaarde op deze manier wordt gewijzigd.
Dus in wezen is de truc om de operator CString offer te gebruiken en dit te krijgen:
LPTSTR lptstr = (LPCTSTR) string; // CString provide this operator overload
LPTSTR kan nu verder worden getypecast naar LPSTR 🙂
dispinfo.item.pszText = LPTSTR( lpfzfd); // accomplish the cheat :P
De juiste manier om LPTSTR
van ‘CString’ te krijgen is echter deze (compleet voorbeeld):
CString str = _T("Hello");
LPTSTR lpstr = str.GetBuffer(str.GetAllocLength());
str.ReleaseBuffer(); // you must call this function if you change the string above with the pointer
Nogmaals omdat de GetBuffer()retourneert LPTSTR
om die reden die je nu kunt wijzigen 🙂