LPCSTR, LPCTSTR ve LPTSTR


109

Ne arasındaki fark LPCSTR, LPCTSTRve LPTSTR?

Bir dizgeyi bir dizgeye dönüştürmek için neden bunu yapmamız gerekiyor? LV / _ITEMyapı değişkeninepszText :

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

2
"String" türünün tam olarak ne olduğunu söyleyebilir misiniz? (örneğin CString)
John Sibly

Yanıtlar:


122

Sorunuzun ilk bölümünü cevaplamak için:

LPCSTRconst dizgesine bir göstericidir (LP, Uzun İşaretçi anlamına gelir )

LPCTSTRbir const TCHARdizeye bir göstericidir ( TCHARprojenizde UNICODE'un tanımlanıp tanımlanmadığına bağlı olarak geniş karakter veya karakter olabilir)

LPTSTR(const olmayan) bir TCHARdizeye bir göstericidir

Pratikte, geçmişte bunlar hakkında konuşurken, basitlik için "işaretçi" ifadesini dışarıda bıraktık, ancak yörüngedeki hafiflik yarışları tarafından belirtildiği gibi bunların hepsi birer işaretçi.

Bu, C ++ dizelerini açıklayan harika bir kod proje makalesidir (farklı türleri karşılaştıran bir grafik için aşağı doğru 2 / 3'e bakın)


18
Hepsi yanlış. Bunların hiçbiri dizge değildir. Bunların hepsi birer işaret. -1
Yörüngede Hafiflik Yarışları

8
@LightnessRacesinOrbit Teknik olarak haklısınız - tecrübelerime göre, C ++ 'da dizge türlerine atıfta bulunurken kısalık için "işaretçi ...." açıklamasını dışarıda bırakmak yaygın bir uygulamadır
John Sibly

2
@JohnSably: C dilinde, evet. C ++ 'da kesinlikle olmamalı !!
Orbit'te Hafiflik Yarışları

4
Bu kod projesi makalesinin 15 yıl önce yazıldığına ve güncellenmediği sürece Unicode karakterlerinin her zaman 2 bayt olduğu hakkında yanıltıcı varsayımlar içerdiğine dikkat edin. Bu tamamen yanlış. UTF16 bile değişken uzunluktadır ... Geniş karakterlerin UCS-2 kodlu olduğunu ve bu bağlamda "Unicode" un UCS-2'yi ifade ettiğini söylemek çok daha iyidir.
u8it

1
Hmm ... bu durumda, @LightnessRacesinOrbit, C ++ 'daki C-dizelerine atıfta bulunurken, eğer ve yalnızca-özellikle (bozulmuş) dize değişmezleri veya C dilinde yazılmış kodla arabirim oluştururken / çalışırken, C ++ türleri yerine C türlerine dayanır ve / veya extern "C". Bunun dışında, evet, kesinlikle ya "işaretçi" bitine ya da bir C dizesi olarak belirli bir açıklamaya ihtiyaç duymalıdır.
Justin Time - Monica'yı Yeniden

87

Hızlı ve kirli:

LP== L ong P ointer. İşaretçiyi veya karakteri düşün *

C= C onst, bu durumda, karakter dizesinin sabit olan gösterici değil, sabit olduğunu kastettiklerini düşünüyorum.

STRolduğu dize

bu T, derleme seçeneklerine bağlı olarak geniş bir karakter veya karakter (TCHAR) içindir.


16
T geniş karakter için değil, değişen karakter tipi içindir. W geniş içindir (WCHAR'da olduğu gibi). UNICODE tanımlanmışsa, TCHAR == WCHAR, aksi takdirde TCHAR == CHAR. Yani UNICODE tanımlı değilse, LPCTSTR == LPCSTR.
jalf

10
bu yüzden "derleme seçeneklerine bağlı olarak" yazdım
Tim

14
Bu tür açıklamaları gerçekten çok seviyorum :). Çok teşekkürler
Dzung Nguyen

@jalf, T ne anlama geliyor?
Pacerier


36

8 bit AnsiStrings

  • char: 8 bit karakter - temel alınan C / C ++ veri türü
  • CHAR: alias of char- Windows veri türü
  • LPSTR: boş sonlu dizge CHAR ( L ong P ointer)
  • LPCSTR: sabit boş sonlu dizi CHAR ( L ong P ointer)

16 bit UnicodeStrings

  • wchar_t: 16 bit karakter - temel alınan C / C ++ veri türü
  • WCHAR: alias of wchar_t- Windows veri türü
  • LPWSTR: boş sonlu dizge WCHAR ( L ong P ointer)
  • LPCWSTR: sabit boş sonlu dizi WCHAR ( L ong P ointer)

UNICODEtanımlamaya bağlı olarak

  • TCHAR: WCHARUNICODE tanımlanmışsa takma adı ; aksi takdirdeCHAR
  • LPTSTR: boş sonlu dizge TCHAR ( L ong P ointer)
  • LPCTSTR: sabit boş sonlu dizi TCHAR ( L ong P ointer)

Yani

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

Bonus Okuma

TCHARMetin Karakteri ( arşiv.is )


4
Utanç verici bu cevap asla zirveye çıkmayacak çünkü çok yeni .. Bu gerçekten SO'nun düzeltmesi gereken bir şey. Şimdiye kadarki en iyi cevap bu.
Dan Bechard

İşte Unicode projesini yaparken bu bana gerçekten çok yardımcı oluyor. Teşekkürler!
Yoon5oo

Güzel cevap. Unicode sürümünün UTF16 kullandığını eklemeye değer olduğunu düşünüyorum, bu nedenle her 16 bitlik yığın bir karakter değil, bir kod birimidir. İsimler tarihseldir (Unicode === UCS2 olduğunda).
Margaret Bloom

5

John ve Tim'in cevabına ekleniyor.

Win98 için kodlamadığınız sürece, uygulamanızda kullanmanız gereken 6+ dize türünden yalnızca ikisi vardır.

  • LPWSTR
  • LPCWSTR

Geri kalanı ANSI platformlarını veya ikili derlemeleri desteklemek içindir. Bunlar eskisi kadar bugün alakalı değil.


2
@BlueRaja, cevabımda esas olarak C tabanlı dizelerden bahsediyordum. Ancak C ++ için kaçınmak isterim std::stringçünkü hala ASCII tabanlı bir dizedir ve std::wstringonun yerine tercih eder .
JaredPar

1
İşlevlerin ASCII (* A) veya geniş karakterli (* W) sürümlerini doğrudan çağırmadığınız sürece LPTSTR ve LPCTSTR kullanıyor olmalısınız. Derlerken belirlediğiniz karakter genişliğinin takma adlarıdır.
osvein

... Ve şimdi Microsoft, *AWinAPI sürümlerini UTF-8 kod sayfasıyla uyumlu hale getirmeye çalıştığına göre, birdenbire çok daha alakalı hale geldi. ; P
Justin Time - Monica'yı eski

4

Sorunuzun ikinci bölümünü cevaplamak için aşağıdaki gibi şeyler yapmanız gerekir:

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

çünkü MS'in LVITEMyapısı bir LPTSTR, yani değiştirilebilir bir T-dizgisi işaretleyicisine sahip, bir değil LPCTSTR. Ne yapıyorsun

1) string( CStringa tahmininde) birLPCTSTR yı (pratikte karakter tamponunun adresini salt okunur bir işaretçi olarak almak anlamına gelir) dönüştür

2) o salt okunur işaretçiyi const-ness'ını atarak yazılabilir bir işaretçiye dönüştürün .

Aramanızın bunun üzerinden yazmaya çalışarak sona dispinfoerme şansı olup olmadığı, neyin kullanıldığına bağlıdır .ListViewpszText . Eğer öyleyse, bu potansiyel olarak çok kötü bir şeydir: Sonuçta size salt okunur bir işaretçi verilmiş ve sonra onu yazılabilir olarak değerlendirmeye karar vermişsiniz: belki de salt okunur olmasının bir nedeni vardır!

Eğer birlikte CStringçalışıyorsanız, kullanma seçeneğiniz vardır string.GetBuffer()- bu size kasıtlı olarak yazılabilirlik sağlar LPTSTR. Ardından ReleaseBuffer(), dizge değişirse aramayı hatırlamanız gerekir . Veya yerel bir geçici tampon ayırabilir ve dizeyi oraya kopyalayabilirsiniz.

Zamanın% 99'u gereksiz olacak ve LPCTSTRbir LPTSTRirade gibi davranmak işe yarayacak ... ama bir gün, hiç beklemediğin zaman ...


1
C tarzı dökümden kaçınmalı ve xxx_cast<>()bunun yerine kullanmalısınız .
harper

@harper Haklısınız - ama OP'den alıntı yapıyordum, sorduğu kod buydu. Kodu kendim xxx_cast<>yazsaydım, iki farklı parantez tabanlı döküm stilini karıştırmak yerine kesinlikle kullanırdı !
AAT
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.