LPCSTR, LPCTSTR và LPTSTR


109

Có gì chênh lệch giữa LPCSTR, LPCTSTRLPTSTR?

Tại sao chúng ta cần làm điều này để chuyển đổi một chuỗi thành một biến LV/ _ITEMcấu trúc pszText:

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

2
Bạn có thể nói chính xác loại "chuỗi" là gì không? (ví dụ: CString)
John Sither

Câu trả lời:


122

Để trả lời phần đầu tiên của câu hỏi của bạn:

LPCSTRlà một con trỏ đến một chuỗi const (LP có nghĩa là Con trỏ dài )

LPCTSTRlà một con trỏ đến một const TCHARchuỗi, ( TCHARlà một ký tự rộng hoặc ký tự tùy thuộc vào việc UNICODE có được xác định trong dự án của bạn hay không)

LPTSTRlà một con trỏ đến một (không const) TCHARchuỗi

Trong thực tế khi nói về những điều này trong quá khứ, chúng ta đã bỏ qua cụm từ "con trỏ tới một" cho đơn giản, nhưng như đã đề cập bởi sự nhẹ nhàng-chủng tộc-trong quỹ đạo, chúng đều là con trỏ.

Đây là một bài viết về codeproject tuyệt vời mô tả các chuỗi C ++ (xem 2/3 đường xuống để biết biểu đồ so sánh các loại khác nhau)


18
Sai hết. Không có thứ nào trong số này là chuỗi. Chúng đều là con trỏ. -1
Các cuộc đua ánh sáng trong quỹ đạo

8
@LightnessRacesinOrbit Bạn là chính xác về mặt kỹ thuật - mặc dù theo kinh nghiệm của tôi nó là thực tế phổ biến để bỏ qua "con trỏ đến một ...." mô tả cho ngắn gọn khi đề cập đến các loại chuỗi trong C ++
John Sibly

2
@JohnSibly: Trong C, có. Trong C ++, nó hoàn toàn không nên !!
Lightness Races in Orbit

4
Lưu ý rằng bài viết codeproject đó đã được viết cách đây 15 năm và, trừ khi nó được cập nhật, có chứa các giả định sai lầm về các ký tự Unicode luôn là 2 byte. Điều đó hoàn toàn sai. Ngay cả UTF16 cũng có độ dài thay đổi ... tốt hơn nhiều nếu nói rằng các ký tự rộng được mã hóa UCS-2 và "Unicode" trong ngữ cảnh này đề cập đến UCS-2.
u8it

1
Hmm ... trong trường hợp này, @LightnessRacesinOrbit, tôi sẽ thêm một phụ lục mà bạn có thể bỏ qua "con trỏ tới a ..." khi đề cập đến chuỗi C trong C ++, nếu-và-chỉ-nếu đề cập cụ thể đến (đã phân rã) chuỗi ký tự hoặc khi giao tiếp / làm việc với mã được viết bằng C, dựa trên các loại C thay vì các loại C ++ và / hoặc có liên kết C thông qua extern "C". Ngoài điều đó, vâng, nó chắc chắn cần phải có bit "con trỏ" hoặc mô tả cụ thể dưới dạng chuỗi C.
Justin Time - Phục hồi Monica.

87

Nhanh chóng và hèn hạ:

LP== L ong P ointer. Chỉ nghĩ con trỏ hoặc ký tự *

C= C onst, trong trường hợp này, tôi nghĩ rằng họ có nghĩa là chuỗi ký tự là một const, không phải là con trỏ là const.

STRchuỗi

những Tlà dành cho một nhân vật rộng hoặc char (TCHAR) tùy thuộc vào tùy chọn biên dịch.


16
T không dành cho ký tự rộng, nó dành cho các loại ký tự khác nhau. W là rộng (như trong WCHAR). Nếu UNICODE được xác định, TCHAR == WCHAR, ngược lại TCHAR == CHAR. Vì vậy, nếu UNICODE không được xác định, LPCTSTR == LPCSTR.
jalf

10
đó là lý do tại sao tôi đã viết "tùy thuộc vào các tùy chọn biên dịch"
Tim

14
Tôi thực sự thích kiểu giải thích này :). Cảm ơn rất nhiều
Dzung Nguyen

@jalf, Vậy T là viết tắt của từ gì?
Pacerier


36

Chuỗi Ansi 8 bit

  • char: Ký tự 8 bit - kiểu dữ liệu C / C ++ cơ bản
  • CHAR: bí danh của char- Kiểu dữ liệu Windows
  • LPSTR: chuỗi được kết thúc bằng null của CHAR ( L ong P ointer)
  • LPCSTR: chuỗi được kết thúc bằng null không đổi của CHAR ( L ong P ointer)

Chuỗi Unicode 16-bit

  • wchar_t: Ký tự 16 bit - kiểu dữ liệu C / C ++ cơ bản
  • WCHAR: bí danh của wchar_t- Kiểu dữ liệu Windows
  • LPWSTR: chuỗi được kết thúc bằng null của WCHAR ( L ong P ointer)
  • LPCWSTR: chuỗi được kết thúc bằng null không đổi của WCHAR ( L ong P ointer)

tùy thuộc vào UNICODExác định

  • TCHAR: bí danh của WCHARnếu UNICODE được xác định; nếu không thìCHAR
  • LPTSTR: chuỗi được kết thúc bằng null của TCHAR ( L ong P ointer)
  • LPCTSTR: chuỗi được kết thúc bằng null không đổi của TCHAR ( L ong P ointer)

Vì thế

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

Đọc thêm

TCHARText Char ( archive.is )


4
Câu trả lời xấu hổ này sẽ không bao giờ lọt vào top đầu vì nó quá mới .. đó thực sự là điều SO cần phải sửa. Đây là câu trả lời tốt nhất cho đến nay.
Dan Bechard

Điều này thực sự giúp ích cho tôi rất nhiều trong khi tôi đang làm dự án Unicode tại nơi làm việc. Cảm ơn!
Yoon5oo

Câu trả lời rất hay. Tôi nghĩ cần thêm rằng phiên bản unicode sử dụng UTF16, vì vậy mỗi đoạn 16 bit không phải là một ký tự mà là một đơn vị mã. Các tên là lịch sử (khi Unicode === UCS2).
Margaret Bloom

5

Thêm vào câu trả lời của John và Tim.

Trừ khi bạn đang viết mã cho Win98, chỉ có hai trong số hơn 6 loại chuỗi mà bạn nên sử dụng trong ứng dụng của mình

  • LPWSTR
  • LPCWSTR

Phần còn lại nhằm hỗ trợ nền tảng ANSI hoặc biên dịch kép. Những điều đó ngày nay không còn phù hợp như trước đây nữa.


2
@BlueRaja, tôi chủ yếu đề cập đến chuỗi dựa trên C trong câu trả lời của mình. Nhưng đối với C ++, tôi sẽ tránh std::stringvì nó vẫn là một chuỗi dựa trên ASCII và std::wstringthay vào đó thích hơn .
JaredPar

1
Bạn nên sử dụng LPTSTR và LPCTSTR trừ khi bạn đang gọi trực tiếp phiên bản hàm ASCII (* A) hoặc widechar (* W). Chúng là bí danh của bất kỳ chiều rộng ký tự nào bạn chỉ định khi biên dịch.
osvein

... Và bây giờ Microsoft đang làm việc để làm cho các *Aphiên bản của WinAPI tương thích với trang mã UTF-8, chúng đột nhiên phù hợp hơn rất nhiều. ; P
Justin Time - Phục hồi Monica

4

Để trả lời phần thứ hai của câu hỏi, bạn cần làm những việc như

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

bởi vì LVITEMcấu trúc của MS có một LPTSTR, tức là một con trỏ chuỗi T có thể thay đổi , không phải là một LPCTSTR. Những gì bạn đang làm là

1) chuyển đổi string(a CStringkhi đoán) thành một LPCTSTR(trong thực tế có nghĩa là lấy địa chỉ của bộ đệm ký tự của nó dưới dạng con trỏ chỉ đọc)

2) chuyển đổi con trỏ chỉ đọc đó thành một con trỏ có thể ghi bằng cách loại bỏ const-ness của nó .

Nó phụ thuộc vào những gì dispinfođược sử dụng để có hay không có khả năng ListViewcuộc gọi của bạn sẽ cố gắng viết thông qua đó hay không pszText. Nếu đúng như vậy, đây là một điều tiềm ẩn rất xấu: sau cùng thì bạn đã được cấp một con trỏ chỉ đọc và sau đó quyết định coi nó là có thể ghi: có thể có lý do khiến nó ở chế độ chỉ đọc!

Nếu đó là một CStringbạn đang làm việc với bạn, bạn có tùy chọn để sử dụng string.GetBuffer()- điều đó cố tình cung cấp cho bạn một quyền ghi LPTSTR. Sau đó, bạn phải nhớ gọi ReleaseBuffer()nếu chuỗi bị thay đổi. Hoặc bạn có thể cấp phát một bộ đệm tạm thời cục bộ và sao chép chuỗi vào đó.

99% thời gian điều này sẽ là không cần thiết và coi LPCTSTRnhư một LPTSTRcông việc sẽ làm ... nhưng một ngày nào đó, khi bạn ít mong đợi nhất ...


1
Bạn nên tránh sử dụng kiểu C và sử dụng xxx_cast<>()thay thế.
harper

@harper Bạn khá đúng - nhưng tôi đang trích dẫn OP, đó là mã mà anh ấy đang hỏi. Nếu tôi tự viết mã, nó chắc chắn sẽ được sử dụng xxx_cast<>thay vì trộn hai kiểu đúc dựa trên dấu ngoặc vuông khác nhau!
AAT
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.