В чем разница между LPCSTR
, LPCTSTR
и LPTSTR
?
Почему нам нужно это сделать, чтобы преобразовать строку в переменную структуры LV
/ _ITEM
pszText
:
LV_DISPINFO dispinfo;
dispinfo.item.pszText = LPTSTR((LPCTSTR)string);
В чем разница между LPCSTR
, LPCTSTR
и LPTSTR
?
Почему нам нужно это сделать, чтобы преобразовать строку в переменную структуры LV
/ _ITEM
pszText
:
LV_DISPINFO dispinfo;
dispinfo.item.pszText = LPTSTR((LPCTSTR)string);
Чтобы ответить на первую часть вашего вопроса:
LPCSTR
- указатель на константную строку (LP означает длинный указатель)
LPCTSTR
- указатель на const TCHAR
строку (TCHAR
является либо широким символом, либо символом, в зависимости от того, определен ли UNICODE в вашем проекте)
LPTSTR
- указатель на (неконстантную) TCHAR
строку
На практике, когда мы говорили об этом в прошлом, мы для простоты опускали фразу «указатель на», но, как упоминалось в lightness-races-in-orbit, все они являются указателями.
Это отличная статья codeproject, описывающая строки C ++ (см. 2/3 пути вниз для диаграммы, сравнивающей различные типы)
extern "C"
. Кроме того, да, ему определенно понадобится либо бит указателя, либо конкретное описание в виде строки C.
- person Justin Time - Reinstate Monica; 11.09.2019
Быстро и грязно:
LP
== L ong P ointer. Подумайте только о указателе или символе *
C
= C onst, в этом случае, я думаю, они означают, что символьная строка является константой, а не указателем, являющимся константой.
STR
- это строка
T
предназначен для широкого символа или символа (TCHAR) в зависимости от параметров компиляции.
char
: 8-битный символ (базовый тип данных C / C ++)CHAR
: псевдоним char
(тип данных Windows)LPSTR
: строка с нулевым символом в конце CHAR
(L ong P ointer)LPCSTR
: константная строка с завершающим нулем для CHAR
(L ong P ointer C onstant)wchar_t
: 16-битный символ (базовый тип данных C / C ++)WCHAR
: псевдоним wchar_t
(тип данных Windows)LPWSTR
: строка с нулевым символом в конце WCHAR
(L ong P ointer)LPCWSTR
: константная строка с завершающим нулем для WCHAR
(L ong P ointer C onstant)UNICODE
определитьTCHAR
: псевдоним WCHAR
, если определен UNICODE; в противном случае CHAR
LPTSTR
: строка с нулевым символом в конце TCHAR
(L ong P ointer)LPCTSTR
: константная строка с завершающим нулем для TCHAR
(L ong P ointer C onstant)So:
Item | 8-bit (Ansi) | 16-bit (Wide) | Varies |
---|---|---|---|
character | CHAR |
WCHAR |
TCHAR |
string | LPSTR |
LPWSTR |
LPTSTR |
string (const) | LPCSTR |
LPCWSTR |
LPCTSTR |
TCHAR
→ Text Char (archive.is)
Почему 8-битная кодовая страница по умолчанию называется ANSI?
Из Unicode и Windows XP
Кэти Виссинк.
Менеджер программы, Глобализация Windows
Корпорация Microsoft
Май 2002 г.
Несмотря на лежащую в основе поддержку Unicode в Windows NT 3.1, поддержка кодовых страниц по-прежнему необходима для многих приложений и компонентов более высокого уровня, включенных в систему, что скорее объясняет повсеместное использование версий A [ANSI] интерфейсов API Win32. чем версии «W» [«широкий» или Unicode]. (Термин «ANSI», используемый для обозначения кодовых страниц Windows, является исторической справкой, но в настоящее время это неправильное название, которое продолжает сохраняться в сообществе Windows. Источником этого является тот факт, что кодовая страница Windows 1252 изначально была основана на черновик ANSI, который стал стандартом ISO 8859-1. Однако при добавлении кодовых точек к диапазону, зарезервированному для управляющих кодов в стандарте ISO, кодовая страница Windows 1252 и последующие кодовые страницы Windows, первоначально основанные на серии ISO 8859-x, отклонились из ISO. По сей день нередко сообщества разработчиков, как внутри, так и за пределами Microsoft, путают кодовую страницу 8859-1 с Windows 1252, а также видят «ANSI» или «A», используемые для обозначения Windows поддержка кодовой страницы.)
Добавление к ответу Джона и Тима.
Если вы не пишете код для Win98, есть только два из 6+ строковых типов, которые вы должны использовать в своем приложении.
LPWSTR
LPCWSTR
Остальные предназначены для поддержки платформ ANSI или двойной компиляции. Сегодня это уже не так актуально, как раньше.
std::string
, потому что это все еще строка на основе ASCII, и предпочел бы вместо этого std::wstring
.
- person JaredPar; 12.05.2010
*A
версий WinAPI с кодовой страницей UTF-8, они внезапно стали намного более актуальными. ;П
- person Justin Time - Reinstate Monica; 13.09.2019
Чтобы ответить на вторую часть вашего вопроса, вам нужно сделать такие вещи, как
LV_DISPINFO dispinfo;
dispinfo.item.pszText = LPTSTR((LPCTSTR)string);
потому что структура MS LVITEM
имеет LPTSTR
, то есть изменяемый указатель T-строки, а не LPCTSTR
. Что ты делаешь
1) преобразовать string
(CString
в предположении) в LPCTSTR
(что на практике означает получение адреса его символьного буфера в виде указателя только для чтения)
2) преобразовать этот доступный только для чтения указатель в записываемый указатель, отбросив его const
-сущность.
Это зависит от того, для чего dispinfo
используется, есть ли вероятность, что ваш ListView
вызов в конечном итоге попытается записать через этот pszText
. Если да, то это потенциально очень плохо: в конце концов, вам дали указатель только для чтения, а затем вы решили рассматривать его как доступный для записи: возможно, есть причина, по которой он был доступен только для чтения!
Если это CString
, с которым вы работаете, у вас есть возможность использовать string.GetBuffer()
, что намеренно дает вам доступный для записи LPTSTR
. Затем вы должны не забыть вызвать ReleaseBuffer()
, если строка действительно изменилась. Или вы можете выделить локальный временный буфер и скопировать туда строку.
В 99% случаев в этом нет необходимости, и обращение с LPCTSTR
как с LPTSTR
будет работать ... но однажды, когда вы меньше всего этого ожидаете ...
xxx_cast<>()
.
- person harper; 27.06.2018
xxx_cast<>
вместо того, чтобы смешивать два разных стиля кастинга на основе скобок!
- person AAT; 12.10.2018
Краткий ответ на вторую часть вопроса заключается в том, что класс CString
не обеспечивает прямое преобразование приведения типов по дизайну, и то, что вы делаете, является своего рода читерством.
Более длинный ответ следующий:
Причина, по которой вы можете преобразовать CString
в LPCTSTR
, заключается в том, что CString предоставляет эту возможность, переопределяя operator=
. По дизайну он обеспечивает преобразование только в указатель LPCTSTR
, поэтому строковое значение не может быть изменено с помощью этого указателя.
Другими словами, он просто не предоставляет перегрузки operator=
для преобразования CString
в LPSTR
по той же причине, что и выше. Они не хотят позволять изменять строковое значение таким образом.
По сути, фокус состоит в том, чтобы использовать оператор CString, предоставленный и получить следующее:
LPTSTR lptstr = (LPCTSTR) string; // CString provide this operator overload
Теперь LPTSTR можно преобразовать в LPSTR :)
dispinfo.item.pszText = LPTSTR( lpfzfd); // accomplish the cheat :P
Правильный способ получить LPTSTR
из CString - это (полный пример):
CString str = _T("Hello");
LPTSTR lpstr = str.GetBuffer(str.GetAllocLength());
str.ReleaseBuffer(); // you must call this function if you change the string above with the pointer
Опять же, потому что GetBuffer () возвращает LPTSTR
по этой причине, теперь вы можете изменить :)