Jaka jest różnica między LPCSTR
, LPCTSTR
i LPTSTR
?
Dlaczego musimy to zrobić, aby przekonwertować ciąg na zmienną LV
/ _ITEM
structure pszText
:
LV_DISPINFO dispinfo;
dispinfo.item.pszText = LPTSTR((LPCTSTR)string);
Jaka jest różnica między LPCSTR
, LPCTSTR
i LPTSTR
?
Dlaczego musimy to zrobić, aby przekonwertować ciąg na zmienną LV
/ _ITEM
structure pszText
:
LV_DISPINFO dispinfo;
dispinfo.item.pszText = LPTSTR((LPCTSTR)string);
Odpowiedzi:
Aby odpowiedzieć na pierwszą część pytania:
LPCSTR
jest wskaźnikiem na ciąg znaków const (LP oznacza długi wskaźnik )
LPCTSTR
jest wskaźnikiem do const TCHAR
łańcucha ( TCHAR
będącego szerokim znakiem lub znakiem w zależności od tego, czy w projekcie zdefiniowano UNICODE)
LPTSTR
jest wskaźnikiem do (nie stałego) TCHAR
ciągu
W praktyce, kiedy mówiliśmy o nich w przeszłości, pominęliśmy „wskaźnik do” wyrażenia dla uproszczenia, ale jak wspomniano w lekkich wyścigach na orbicie, wszystkie one są wskazówkami.
To jest świetny artykuł o projekcie kodu opisujący ciągi C ++ (patrz 2/3 drogi w dół, aby zobaczyć wykres porównujący różne typy)
extern "C"
. Poza tym, tak, zdecydowanie powinien potrzebować bitu „wskaźnika” lub konkretnego opisu jako napisu w C.
Szybko i brudno:
LP
== L ong P ointer. Po prostu pomyśl o wskaźniku lub znaku *
C
= C onst, w tym przypadku myślę, że oznaczają one ciąg znaków, a nie wskaźnik będący stałą.
STR
jest ciągiem
T
jest dla szerokiego znaku lub char (TCHAR) w zależności od opcji kompilacji.
char
: Znak 8-bitowy - podstawowy typ danych C / C ++CHAR
: alias char
- typ danych WindowsLPSTR
: zakończony zerem ciąg CHAR
( L ong P ointer)LPCSTR
: stały ciąg zakończony zerem CHAR
( L ong P ointer)wchar_t
: Znak 16-bitowy - podstawowy typ danych C / C ++WCHAR
: alias wchar_t
- typ danych WindowsLPWSTR
: zakończony zerem ciąg WCHAR
( L ong P ointer)LPCWSTR
: stały ciąg zakończony zerem WCHAR
( L ong P ointer)UNICODE
zdefiniowaniaTCHAR
: alias WCHAR
jeśli zdefiniowano UNICODE; InaczejCHAR
LPTSTR
: zakończony zerem ciąg TCHAR
( L ong P ointer)LPCTSTR
: stały ciąg zakończony zerem TCHAR
( L ong P ointer)Więc
| Item | 8-bit | 16-bit | Varies |
|-------------------|--------------|-------------|-----------------|
| character | CHAR | WCHAR | TCHAR |
| string | LPSTR | LPWSTR | LPTSTR |
| string (const) | LPCSTR | LPCWSTR | LPCTSTR |
TCHAR
→ Tekst Char ( archive.is )
Dodawanie do odpowiedzi Johna i Tima.
Jeśli nie piszesz dla Win98, istnieją tylko dwa z ponad 6 typów ciągów, których powinieneś używać w swojej aplikacji
LPWSTR
LPCWSTR
Reszta jest przeznaczona do obsługi platform ANSI lub podwójnych kompilacji. Nie są one dziś tak aktualne, jak kiedyś.
std::string
ponieważ nadal jest to ciąg oparty na ASCII i wolę std::wstring
zamiast tego.
*A
dostosowaniem wersji WinAPI do strony kodowej UTF-8, nagle stają się one znacznie bardziej odpowiednie. ; P
Aby odpowiedzieć na drugą część pytania, musisz wykonać takie czynności jak
LV_DISPINFO dispinfo;
dispinfo.item.pszText = LPTSTR((LPCTSTR)string);
ponieważ LVITEM
struktura MS ma plikLPTSTR
, tj. zmienny wskaźnik łańcucha T, a nie LPCTSTR
. To, co robisz, jest
1) przekonwertować string
( CString
przypuszczalnie a) na LPCTSTR
(co w praktyce oznacza uzyskanie adresu bufora znaków jako wskaźnika tylko do odczytu)
2) przekonwertować ten wskaźnik tylko do odczytu na wskaźnik z możliwością zapisu, odrzucając jego const
-ness.
Zależy to od tego, co dispinfo
zostanie użyte do tego, czy jest szansa, że twoja ListView
rozmowa zakończy się próbą napisania przez to pszText
. Jeśli tak, jest to potencjalnie bardzo zła rzecz: w końcu otrzymałeś wskaźnik tylko do odczytu i zdecydowałeś traktować go jako zapisywalny: może jest powód, dla którego był on tylko do odczytu!
Jeśli jest to plik, z CString
którym pracujesz, masz możliwość użycia string.GetBuffer()
- to celowo daje ci możliwość zapisuLPTSTR
. Musisz wtedy pamiętać o wywołaniu, ReleaseBuffer()
jeśli łańcuch się zmieni. Lub możesz przydzielić lokalny bufor tymczasowy i skopiować tam ciąg.
W 99% przypadków będzie to niepotrzebne i traktowanie tego LPCTSTR
jako LPTSTR
dobrego zadziała ... ale pewnego dnia, kiedy najmniej się tego spodziewasz ...
xxx_cast<>()
zamiast tego używać .
xxx_cast<>
zamiast mieszania dwóch różnych stylów rzutowania opartych na nawiasach!