LPCSTR, LPCTSTR และ LPTSTR


109

สิ่งที่แตกต่างระหว่างLPCSTR, LPCTSTRและLPTSTR?

ทำไมเราต้องทำสิ่งนี้เพื่อแปลงสตริงเป็นตัวแปรLV/ _ITEMโครงสร้างpszText:

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

2
คุณบอกได้ไหมว่า "สตริง" คืออะไร (เช่น CString)
John Sably

คำตอบ:


124

เพื่อตอบคำถามส่วนแรกของคุณ:

LPCSTRเป็นตัวชี้ไปยังสตริง const (LP หมายถึงLong Pointer )

LPCTSTRเป็นตัวชี้ไปยังconst TCHARสตริง ( TCHARเป็นอักขระแบบกว้างหรืออักขระแบบกว้างขึ้นอยู่กับว่า UNICODE ถูกกำหนดไว้ในโครงการของคุณหรือไม่)

LPTSTRเป็นตัวชี้ไปยังTCHARสตริง(ไม่ใช่ const)

ในทางปฏิบัติเมื่อพูดถึงสิ่งเหล่านี้ในอดีตเราได้ทิ้งวลี "ตัวชี้ไปที่" ไว้เพื่อความเรียบง่าย แต่ตามที่กล่าวไว้โดยความสว่าง - การแข่งขันในวงโคจรนั้นเป็นตัวชี้ทั้งหมด

นี่เป็นบทความ codeprojectที่ยอดเยี่ยมที่อธิบายถึงสตริง C ++ (ดู 2/3 ทางลงสำหรับแผนภูมิเปรียบเทียบประเภทต่างๆ)


18
ผิดทั้งหมด. ไม่มีสิ่งเหล่านี้เป็นสตริง พวกเขาทั้งหมดเป็นตัวชี้ -1
Lightness Races ใน Orbit

9
@LightnessRacesinOrbit คุณมีความถูกต้องในทางเทคนิค - แม้ว่าจากประสบการณ์ของฉันมันเป็นเรื่องธรรมดาที่จะทิ้งคำอธิบาย "ตัวชี้ไปที่ .... " สำหรับความกะทัดรัดเมื่ออ้างถึงประเภทสตริงใน C ++
John Sably

2
@JohnSably: ใน C ใช่ ในภาษา C ++ ไม่ควรอย่างยิ่ง !!
Lightness Races ใน Orbit

4
โปรดสังเกตว่าบทความ codeproject นั้นเขียนขึ้นเมื่อ 15 ปีที่แล้วและหากไม่ได้รับการอัปเดตจะมีสมมติฐานที่ทำให้เข้าใจผิดเกี่ยวกับอักขระ Unicode ซึ่งมีขนาด 2 ไบต์เสมอ นั่นผิดทั้งหมด แม้ UTF16 จะมีความยาวผันแปรได้ ... มันจะดีกว่ามากที่จะบอกว่าอักขระแบบกว้างนั้นเข้ารหัส UCS-2 และ "Unicode" ในบริบทนี้หมายถึง UCS-2
u8it

1
อืม ... ในกรณีนี้ @LightnessRacesinOrbit ฉันจะเพิ่มภาคผนวกว่าไม่เป็นไรที่จะเว้น "ตัวชี้ไปที่ ... " เมื่ออ้างถึงสตริง C ใน C ++ ถ้า - และ - เท่านั้น - หากอ้างถึงโดยเฉพาะ (เน่า) ตัวอักษรของสตริงหรือเมื่อการเชื่อมต่อ / การทำงานกับรหัสที่เขียนทั้งใน C อาศัยประเภท C แทน C ++ ชนิดและ / extern "C"หรือมีการเชื่อมโยงผ่าน นอกเหนือจากนั้นใช่แล้วมันควรต้องมีบิต "ตัวชี้" หรือคำอธิบายเฉพาะเป็นสตริง C
Justin Time - คืนสถานะ Monica

89

รวดเร็วและสกปรก:

LP== ong P ointer แค่คิดว่าตัวชี้หรือถ่าน *

C = C onst ในกรณีนี้ฉันคิดว่าพวกเขาหมายถึงสตริงอักขระเป็น const ไม่ใช่ตัวชี้ที่เป็น const

STR คือ สตริง

ใช้Tสำหรับอักขระแบบกว้างหรืออักขระ (TCHAR) ขึ้นอยู่กับตัวเลือกการคอมไพล์


16
T ไม่ใช่สำหรับอักขระแบบกว้าง แต่สำหรับประเภทอักขระที่แตกต่างกัน W สำหรับกว้าง (เช่นเดียวกับใน WCHAR) หากมีการกำหนด UNICODE TCHAR == WCHAR หรือ TCHAR == CHAR ดังนั้นหากไม่ได้กำหนด UNICODE ไว้ LPCTSTR == LPCSTR
jalf

10
นั่นคือเหตุผลที่ฉันเขียนว่า "ขึ้นอยู่กับตัวเลือกการคอมไพล์"
Tim

14
ฉันชอบการอธิบายประเภทนี้มาก :) ขอบคุณมาก
Dzung Nguyen

@jalf แล้ว T ย่อมาจากอะไร?
Pacerier


39

AnsiStrings แบบ 8 บิต

  • char: อักขระ 8 บิต - อ้างอิงประเภทข้อมูล C / C ++
  • CHAR: นามแฝงของchar- ประเภทข้อมูล Windows
  • LPSTR: สตริงที่สิ้นสุดด้วย null ของCHAR ( L ong P ointer)
  • LPCSTR: สตริงที่สิ้นสุดด้วย null คงที่ของCHAR ( L ong P ointer)

UnicodeStrings 16 บิต

  • wchar_t: อักขระ 16 บิต - อ้างอิงประเภทข้อมูล C / C ++
  • WCHAR: นามแฝงของwchar_t- ประเภทข้อมูล Windows
  • LPWSTR: สตริงที่สิ้นสุดด้วย null ของWCHAR ( L ong P ointer)
  • LPCWSTR: สตริงที่สิ้นสุดด้วย null คงที่ของWCHAR ( L ong P ointer)

ขึ้นอยู่กับการUNICODEกำหนด

  • TCHAR: นามแฝงของWCHARถ้า UNICODE ถูกกำหนด; มิฉะนั้นCHAR
  • LPTSTR: สตริงที่สิ้นสุดด้วย null ของTCHAR ( L ong P ointer)
  • LPCTSTR: สตริงที่สิ้นสุดด้วย null คงที่ของTCHAR ( L ong P ointer)

ดังนั้น

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

การอ่านโบนัส

TCHARอักขระข้อความ ( archive.is )


4
ความอัปยศคำตอบนี้จะไม่มีทางนำไปสู่จุดสูงสุดเพราะมันใหม่มาก .. นั่นเป็นสิ่งที่ SO ต้องแก้ไขจริงๆ นี่คือคำตอบที่ดีที่สุด
Dan Bechard

สิ่งนี้ช่วยฉันได้มากในขณะที่ฉันกำลังทำโครงการ Unicode ในที่ทำงาน ขอบคุณ!
Yoon5oo

คำตอบที่ดี ฉันคิดว่ามันคุ้มค่าที่จะเพิ่มรุ่น Unicode ใช้ UTF16 ดังนั้นแต่ละ 16 บิตจึงไม่ใช่อักขระ แต่เป็นหน่วยรหัส ชื่อเป็นประวัติ (เมื่อ Unicode === UCS2)
Margaret Bloom

5

เพิ่มคำตอบของ John และ Tim

หากคุณไม่ได้เข้ารหัสสำหรับ Win98 มีเพียงสองประเภทสตริง 6+ ที่คุณควรใช้ในแอปพลิเคชันของคุณ

  • LPWSTR
  • LPCWSTR

ส่วนที่เหลือมีไว้เพื่อรองรับแพลตฟอร์ม ANSI หรือการคอมไพล์แบบคู่ สิ่งเหล่านี้ไม่เกี่ยวข้องกันอย่างที่เคยเป็นมาในปัจจุบัน


2
@BlueRaja ฉันอ้างถึงสตริงตาม C เป็นหลักในคำตอบของฉัน แต่สำหรับ C ++ ฉันจะหลีกเลี่ยงstd::stringเพราะมันยังคงเป็นสตริงที่ใช้ ASCII และชอบstd::wstringแทน
JaredPar

1
คุณควรใช้ LPTSTR และ LPCTSTR เว้นแต่คุณจะเรียกใช้ฟังก์ชันเวอร์ชัน ASCII (* A) หรือ widechar (* W) โดยตรง เป็นนามแฝงของความกว้างอักขระใด ๆ ที่คุณระบุเมื่อคุณคอมไพล์
osvein

... และตอนนี้ Microsoft กำลังดำเนินการเพื่อทำให้*Aเวอร์ชันของ WinAPI เข้ากันได้กับหน้ารหัส UTF-8 พวกเขาก็มีความเกี่ยวข้องมากขึ้น ; P
เวลาจัสติน - คืนสถานะโมนิกา

4

ในการตอบคำถามส่วนที่สองคุณต้องทำสิ่งต่างๆเช่น

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

เพราะของ MS LVITEMstruct มีLPTSTRกล่าวคือไม่แน่นอนชี้ T-สตริงไม่LPCTSTRT-สตริงไม่ สิ่งที่คุณกำลังทำคือ

1) แปลงstring(a CStringโดยเดา) เป็นLPCTSTR(ซึ่งในทางปฏิบัติหมายถึงการรับที่อยู่ของบัฟเฟอร์อักขระเป็นตัวชี้แบบอ่านอย่างเดียว)

2) แปลงตัวชี้แบบอ่านอย่างเดียวนั้นให้เป็นตัวชี้ที่เขียนได้โดยการทิ้งค่าconst-ness

ขึ้นอยู่กับสิ่งที่dispinfoจะใช้ว่ามีโอกาสที่ListViewสายของคุณจะพยายามเขียนผ่านสิ่งนั้นpszTextหรือไม่ ถ้าเป็นเช่นนั้นนี่อาจเป็นสิ่งที่เลวร้ายมาก: หลังจากทั้งหมดคุณได้รับตัวชี้แบบอ่านอย่างเดียวจากนั้นจึงตัดสินใจที่จะถือว่ามันเขียนได้: อาจมีเหตุผลที่มันเป็นแบบอ่านอย่างเดียว!

หากเป็นCStringคุณกำลังทำงานกับคุณมีตัวเลือกในการใช้งานstring.GetBuffer()ซึ่งจงใจให้คุณเขียนLPTSTRได้ จากนั้นคุณต้องจำไว้ว่าต้องโทรReleaseBuffer()หากสตริงมีการเปลี่ยนแปลง หรือคุณสามารถจัดสรรบัฟเฟอร์ชั่วคราวในเครื่องและคัดลอกสตริงลงในนั้น

99% ของเวลานี้จะไม่จำเป็นและถือว่าLPCTSTRเป็นไปได้LPTSTRผล ... แต่วันหนึ่งเมื่อคุณคาดหวังน้อยที่สุด ...


1
คุณควรหลีกเลี่ยงการร่ายแบบ C และใช้xxx_cast<>()แทน
harper

@harper คุณพูดถูก - แต่ฉันกำลังอ้างถึง OP นั่นคือรหัสที่เขาถามถึง ถ้าฉันเขียนโค้ดด้วยตัวเองแน่นอนว่าจะต้องใช้xxx_cast<>มากกว่าการผสมรูปแบบการหล่อแบบยึดสองแบบที่แตกต่างกัน!
AAT
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.