LPCSTR, LPCTSTR dan LPTSTR

109

Apa perbedaan antara LPCSTR, LPCTSTRdan LPTSTR?

Mengapa kita perlu melakukan ini untuk mengubah string menjadi variabel LV/ _ITEMstruktur pszText:

LV_DISPINFO dispinfo;  
dispinfo.item.pszText = LPTSTR((LPCTSTR)string);
tidak ada
sumber
2
Bisakah Anda mengatakan dengan tepat apa jenis "string" itu? (misalnya CString)
John Sibly

Jawaban:

122

Untuk menjawab bagian pertama dari pertanyaan Anda:

LPCSTRadalah pointer ke string const (LP berarti Long Pointer )

LPCTSTRadalah penunjuk ke const TCHARstring, ( TCHARbisa berupa karakter lebar atau karakter tergantung pada apakah UNICODE ditentukan dalam proyek Anda)

LPTSTRadalah penunjuk ke TCHARstring (non-const)

Dalam praktiknya ketika membicarakan hal ini di masa lalu, kita telah meninggalkan frasa "penunjuk ke" untuk kesederhanaan, tetapi seperti yang disebutkan oleh lightness-races-in-orbit semuanya adalah petunjuk.

Ini adalah artikel proyek kode yang bagus yang menjelaskan string C ++ (lihat 2/3 cara ke bawah untuk bagan yang membandingkan berbagai jenis)

John Sibly
sumber
18
Semua salah. Tak satu pun dari hal-hal ini adalah string. Semuanya adalah petunjuk. -1
Balapan Ringan di Orbit
8
@LightnessRacesinOrbit Anda secara teknis benar - meskipun menurut pengalaman saya, merupakan praktik umum untuk mengabaikan deskripsi "penunjuk ke ...." agar singkatnya saat mengacu pada jenis string di C ++
John Sibly
2
@JohnSible: Di C, ya. Di C ++, hal itu tidak boleh dilakukan !!
Balapan Ringan di Orbit
4
Perhatikan bahwa artikel codeproject ditulis 15 tahun yang lalu dan, kecuali jika diperbarui, berisi asumsi yang menyesatkan tentang karakter Unicode selalu 2 byte. Itu sepenuhnya salah. Bahkan UTF16 memiliki panjang variabel ... jauh lebih baik untuk mengatakan bahwa karakter lebar dikodekan dengan UCS-2, dan "Unicode" dalam konteks ini mengacu pada UCS-2.
u8it
1
Hmm ... dalam hal ini, @LightnessRacesinOrbit, saya akan menambahkan tambahan bahwa tidak apa-apa untuk mengabaikan "pointer ke ..." saat merujuk ke C-string di C ++, jika-dan-hanya-jika merujuk secara khusus ke (decayed) string literal, atau saat berinteraksi / bekerja dengan kode yang ditulis dalam C, bergantung pada tipe C alih-alih tipe C ++, dan / atau memiliki tautan C lewat extern "C". Selain itu, ya, itu pasti membutuhkan baik "pointer" bit, atau deskripsi spesifik sebagai string C.
Waktu Justin - Kembalikan Monica
87

Cepat dan kotor:

LP== L ong P ointer. Pikirkan saja pointer atau char *

C= C onst, dalam hal ini, saya pikir yang mereka maksud adalah string karakter adalah sebuah const, bukan penunjuk yang menjadi const.

STRadalah string

yang Tdibuat untuk karakter lebar atau char (TCHAR) tergantung pada opsi kompilasi.

Tim
sumber
16
T bukan untuk karakter lebar, ini untuk tipe karakter yang bervariasi. W untuk lebar (seperti pada WCHAR). Jika UNICODE telah ditentukan, TCHAR == WCHAR, jika tidak TCHAR == CHAR. Jadi jika UNICODE tidak ditentukan, LPCTSTR == LPCSTR.
jalf
10
itulah sebabnya saya menulis "tergantung pada opsi kompilasi"
Tim
14
Saya sangat menyukai jenis penjelasan ini :). Terima kasih banyak
Dzung Nguyen
@jalf, Jadi apa kepanjangan dari T?
Pacerier
3
T berarti T ext
Ian Boyd
36

AnsiString 8-bit

  • char: Karakter 8-bit - tipe data C / C ++ yang mendasari
  • CHAR: alias dari char- tipe data Windows
  • LPSTR: string diakhiri null dari CHAR ( L ong P ointer)
  • LPCSTR: string diakhiri null konstan dari CHAR ( L ong P ointer)

UnicodeString 16-bit

  • wchar_t: Karakter 16-bit - tipe data C / C ++ yang mendasari
  • WCHAR: alias dari wchar_t- tipe data Windows
  • LPWSTR: string diakhiri null dari WCHAR ( L ong P ointer)
  • LPCWSTR: string diakhiri null konstan dari WCHAR ( L ong P ointer)

tergantung pada UNICODEdefinisinya

  • TCHAR: alias WCHARjika UNICODE ditentukan; jika tidakCHAR
  • LPTSTR: string diakhiri null dari TCHAR ( L ong P ointer)
  • LPCTSTR: string diakhiri null konstan dari TCHAR ( L ong P ointer)

Begitu

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

Bonus Membaca

TCHARKarakter Teks ( archive.is )

Ian Boyd
sumber
4
Malu, jawaban ini tidak akan pernah mencapai puncak karena sangat baru .. itu benar-benar sesuatu yang perlu diperbaiki SO. Ini adalah jawaban terbaik sejauh ini.
Dan Bechard
Ini sangat membantu saya saat saya melakukan proyek Unicode di tempat kerja. Terima kasih!
Yoon5oo
Jawaban bagus. Saya pikir perlu ditambahkan bahwa versi unicode menggunakan UTF16, jadi setiap potongan 16-bit bukanlah karakter tetapi unit kode. Nama-nama tersebut historis (ketika Unicode === UCS2).
Margaret Bloom
5

Menambah jawaban John dan Tim.

Kecuali Anda membuat kode untuk Win98, hanya ada dua dari 6+ tipe string yang harus Anda gunakan dalam aplikasi Anda

  • LPWSTR
  • LPCWSTR

Sisanya dimaksudkan untuk mendukung platform ANSI atau kompilasi ganda. Itu tidak lagi relevan hari ini seperti dulu.

JaredPar
sumber
2
@BlueRaja, saya terutama mengacu pada string berbasis C dalam jawaban saya. Tetapi untuk C ++ saya akan menghindari std::stringkarena masih merupakan string berbasis ASCII dan lebih suka std::wstringsebagai gantinya.
JaredPar
1
Anda harus menggunakan LPTSTR dan LPCTSTR kecuali Anda memanggil versi fungsi ASCII (* A) atau widechar (* W) secara langsung. Mereka adalah alias dengan lebar karakter apa pun yang Anda tentukan saat Anda mengompilasi.
osvein
... Dan sekarang Microsoft sedang berupaya membuat *Aversi WinAPI kompatibel dengan halaman kode UTF-8, tiba-tiba mereka jauh lebih relevan. ; P
Waktu Justin - Kembalikan Monica
4

Untuk menjawab bagian kedua dari pertanyaan Anda, Anda perlu melakukan hal-hal seperti

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

karena LVITEMstruct MS memiliki LPTSTR, yaitu pointer T-string yang bisa berubah , bukanLPCTSTR . Apa yang kamu lakukan adalah

1) ubah string( CStringtebakan) menjadiLPCTSTR (yang dalam praktiknya berarti mendapatkan alamat buffer karakternya sebagai penunjuk hanya-baca)

2) ubah penunjuk hanya-baca itu menjadi penunjuk yang dapat ditulisi dengan membuang const-ness - nya.

Itu tergantung apa dispinfoyang digunakan untuk apakah ada kemungkinan bahwa ListViewpanggilan Anda akan berakhir mencoba untuk menulis melalui itu pszText. Jika ya, ini berpotensi menjadi hal yang sangat buruk: setelah semua Anda diberi penunjuk hanya-baca dan kemudian memutuskan untuk memperlakukannya sebagai dapat ditulisi: mungkin ada alasan mengapa itu hanya-baca!

Jika itu adalah CStringAnda bekerja dengan Anda memiliki opsi untuk menggunakan string.GetBuffer()- yang dengan sengaja memberi Anda yang dapat ditulisi LPTSTR. Anda kemudian harus ingat untuk memanggil ReleaseBuffer()jika string berubah. Atau Anda dapat mengalokasikan buffer sementara lokal dan menyalin string ke sana.

99% dari waktu ini tidak perlu dan memperlakukannya LPCTSTRsebagai LPTSTRkeinginan ... tetapi suatu hari, ketika Anda tidak mengharapkannya ...

AAT
sumber
1
Anda harus menghindari cast gaya C dan gunakan xxx_cast<>()sebagai gantinya.
harper
@ Harper Anda benar - tapi saya mengutip OP, itu adalah kode yang dia tanyakan. Jika saya menulis kodenya sendiri, itu pasti akan digunakan xxx_cast<>daripada mencampur dua gaya casting berbasis braket yang berbeda!
AAT