Có gì chênh lệch giữa LPCSTR
, LPCTSTR
và LPTSTR
?
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
/ _ITEM
cấu trúc pszText
:
LV_DISPINFO dispinfo;
dispinfo.item.pszText = LPTSTR((LPCTSTR)string);
Có gì chênh lệch giữa LPCSTR
, LPCTSTR
và LPTSTR
?
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
/ _ITEM
cấu trúc pszText
:
LV_DISPINFO dispinfo;
dispinfo.item.pszText = LPTSTR((LPCTSTR)string);
Câu trả lời:
Để trả lời phần đầu tiên của câu hỏi của bạn:
LPCSTR
là một con trỏ đến một chuỗi const (LP có nghĩa là Con trỏ dài )
LPCTSTR
là một con trỏ đến một const TCHAR
chuỗi, ( TCHAR
là 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)
LPTSTR
là một con trỏ đến một (không const) TCHAR
chuỗ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)
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.
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.
STR
là chuỗi
những T
là 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.
char
: Ký tự 8 bit - kiểu dữ liệu C / C ++ cơ bảnCHAR
: bí danh của char
- Kiểu dữ liệu WindowsLPSTR
: 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)wchar_t
: Ký tự 16 bit - kiểu dữ liệu C / C ++ cơ bảnWCHAR
: bí danh của wchar_t
- Kiểu dữ liệu WindowsLPWSTR
: 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)UNICODE
xác địnhTCHAR
: bí danh của WCHAR
nế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 |
TCHAR
→ Text Char ( archive.is )
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.
std::string
vì nó vẫn là một chuỗi dựa trên ASCII và std::wstring
thay vào đó thích hơn .
*A
phiê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
Để 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ì LVITEM
cấ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 CString
khi đ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 ListView
cuộ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 CString
bạ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 LPCTSTR
như một LPTSTR
công việc sẽ làm ... nhưng một ngày nào đó, khi bạn ít mong đợi nhất ...
xxx_cast<>()
thay thế.
xxx_cast<>
thay vì trộn hai kiểu đúc dựa trên dấu ngoặc vuông khác nhau!