Какво е TCHAR, WCHAR, lpstr, lpwstr, lpctstr (и т.н.)
Много C ++ програмисти, които пишат под Windows често се бъркат над това как тези странни идентификатори TCHAR, LPCTSTR. В тази статия ще се опитам да най-добрият начин да се маркират I. А мъглата на съмнение.
Вие се чудя.
Аз питам котка.
Като цяло, на характера на низ може да бъде представен като 1-ия байт и 2 байта.
Обикновено еднобайтовата кодиране на знаците е ANSI- символ представена в този кодиране всички английски букви. А от 2 байта за кодиране на знаците е UNICODE, които могат да бъдат представлявани от всички останали езици в света.
Visual C ++ компилатор подкрепя Чар и wchar_t като вградени типове данни и ANSI кодировки UNICODE.Hotya имат по-конкретна дефиниция на Unicode, но да се разбере, че е Windows използва 2-байт кодиране за многофункционално приложение, езикова поддръжка.
Да представлява 2-байт Unicode кодиране използва Microsoft Windows-UTF16 кодиране.
Microsoft се превърна в един от първите компании, които започнаха да прилагат подкрепа Unicode в своите операционни системи (семейни на Windows NT).
Какво да направите, ако искате C / C ++ код, за да бъдат независими от кодирането и използване на различни видове кодиране?
TIP. Използвайте обикновените типове данни и имена, за да представляват знаците и редовете.
Например, вместо да се променя следния код:
С цел да се подкрепи многоезични приложения (например, Unicode), можете да пишете код в по-общ начин.
Настройките на проекта в раздела Общи там е параметър, който показва набор от символи в какво кодиране ще състави програмата:
Ако опцията за "употреба Unicode набор от символи», тип TCHAR ще се излъчва тип wchar_t. Ако «настроен Използвайте Multi-байт характер» опция тогавашния TCHAR ще се излъчва в типа на Чар. Чувствайте се свободни да използвате типовете Char и wchar_t и настройките на проекта не засяга използването на тези ключови думи.
TCHAR се определя, както следва:
_UNICODE макро е разрешена, ако изберете «Използване Unicode набор от символи» и след това въведете TCHAR се определя като wchar_t. Когато изберете "употреба Multi-байт набор от символи» TCHAR се определя като знак.
В допълнение, с цел, че има поддръжка на множество знакови набори, използващи обща база код, както и способността да се поддържа много езикови приложения, използвайте специфичната функция (т.е., макроси).
Вместо да се използват strcpy, strlen, strcat (включително защитени опции функция с _S префикс) или wcscpy, wcslen, wcscat (включително защитените опции), по-добре използвайте _tcscpy функция, _tcslen, _tcscat.
Както знаете strlen функция е описана по следния начин:
И wcslen функция е описана по следния начин:
По-добре използвайте _tcslen, което логично е описан, както следва:
WC е Wide Character (Major Glyph). Ето защо, тоалетни функции ще бъдат за широк характер низ (тоест, за низ голям характер) .Such начин _tcs ще означава _T символен низ. И както знаете низа с _T префикс може да бъде знак или wchar_t.
Но в действителност _tcslen (и други функции с _tcs префикс) не функционира, то макроси. Те просто се описва като:
Така TCHAR не е вид, и добавка видове Чар и wchar_t. По този начин позволява да се избере нашия мулти воля заявление езични, или все едно, един многоезичен.
Вие питате защо те се описват като макроси, но не и като пълноправен функция.
Причината е проста: библиотека или DLL може да изнася проста функция със същото име и прототипа (с изключение на концепция за претоварване в C ++).
Например, ако експортирате функция:
Как трябва да се обадите на клиента си. Как да:
_TPrintChar магически може да бъде превърнато в функция получаване две байт характер като аргумент.
За да направите това, ние ще направим две различни функции:
И един прост макрос ще скрие разликите между тях:
Клиентът просто нарича функция, тъй като
Имайте предвид, че TCHAR и _TPrintChar сега ще бъде съвместима с UNICODE или ANSI, а променливата и функция параметър cChar ще бъде сравнима с вида на Чар или wchar_t данни.
Макрос ни позволяват да се заобиколят тези трудности, и да ни позволи да използвате функциите ANSI или UNICODE за нашите герои и струни. Много от Windows-специфични функции са описани по този начин, и за програмист има само една функция (т.е. макро) и това беше добре.
Ето един пример с SetWindowText:
Има само няколко функции в които няма такива макроси, и те само с W наставка или А. Пример на тази функция ReadDirectoryChangesW, който няма еквивалент в ANSI кодиране.
Както знаете, ние използваме двойни кавички, за да представляват струни. Поредицата е предвидено по този начин е ANSI-низ, като всеки символ използва 1 байт. Ето един пример:
Това горната част на линията не е низ UNICODE, и не е подходящ за поддържане на множество езици. За да се получи UNICODE низ трябва да използва префикса L.
Ето един пример:
Поставете предната L и ще получите UNICODE низ. Всички знаци (повтарям, всички знаци) е 2 байта, включително английски букви, интервали, цифри и нулев знак. Размерът на Unicode данни низ винаги ще бъде кратно на 2-ри байт. Unicode символи низ с дължина 7 ще заеме площ от 14 байта. Ако низът Unicode е 15 байта след това не е правилния ред, и че няма да работи във всякакъв контекст.
Също така, линията ще бъде кратно на размера sizeof (TCHAR) в байтове.
Когато имате нужда от твърдо кодирана код, можете да пишете код като този:
Line без префикс е ANSI низ като се отделя с L Unicode низ, и низ с _T префикс и ТЕКСТ зависим компилацията. Отново и ТЕКСТ _T го макроси отново. Те се определят, както следва:
Символ ## е ключът (символично) вмъкнете изявление, че ще се превърне _T ( «Unicode») в L «Unicode», където низът е аргумент за makrosa- освен определя _UNICODE.
Ако _UNICODE не определя _T ( «Unicode») го направят в «Unicode». Ключови изявление вложка съществувала дори в езика С, а това не е нещо специфично свързани с низове, кодирани в VC ++.
За информация, макроси могат да се прилагат не само за струни, но и за героите. Например _T ( "R") на свой ред е L'R 'или, в "R". Т.е. или на характера Unicode или ANSI.
Не, и не веднъж, не можете да използвате макро да конвертирате символ или низ в текста на Unicode и не-Unicode.
Следният код е грешен:
_T ред (в); _T (STR); Съставете глоба режим ANSI, _T (х) се превръща в х и _T (в) заедно с _T (ул) ще се превърне в с и ул.
Но когато изграждането на проекта в режим на Unicode, кодът не е компилиран с:
Аз не бих искал да причини инсулт, вашата интелигентност, както и да обясни защо не работи.
Има няколко функции за конвертиране Mulbaytovyh струни в UNICODE, която скоро ще покаже.
Има един важен момент, почти всички функции, който взема низ или символ, като приоритет в API Windows, имат общото название на MSDN и на други места.
SetWindowTextA функция / W ще бъдат класифицирани като:
Но както знаете, това е просто SetWindowText макро, и в зависимост от настройките на проекта ще се считат за:
Библиотеката User32.dll, има 2 SetWindowTextA SetWindowTextW функции и които се изнасят, а именно, че няма име с родовото наименование.
Всички функции, които имат както ANSI и UNICODE версия, всъщност имат само изпълнението UNICODE. Това означава, че когато се обадите SetWindowTextA от кода си, минавайки параметричния низ ANSI - го преобразува ANSI към UNICODE е SetWindowTextW.
А истинска работа (настройка заглавие / име / етикет на прозореца) прави само Unicode версия!
Вземете още един пример, който ще получи прозореца на текст с помощта GetWindowText.
Наричаш GetWindowTextA подавайки му ANSI буфер като буфер дестинация.
GetWindowTextA първи причини GetWindowTextW, евентуално разпределяне памет за Unicode струни (т.е. wchar_t масив).
След това той се превръща низ Unicode към ANSI за вас.
Това ANSI да Unicode преобразуване не се ограничава само GUI функции, както и работи всичко подгрупата на функцията на Windows API, който се низ и има две възможности.
Ето още един пример за такива функции:
Поради това се препоръчва да се обадите директно на функциите Unicode.
От друга страна, това означава, че винаги трябва да се фокусира върху монтажа на версията Unicode, отколкото версията на събранието ANSI, като се има предвид факта, че сте свикнали да използвате ANSI струни в продължение на години.
Да, можете да запазите и да получите низ ANSI, като например писане във файл, или изпращане на незабавни съобщения на вашата програма за чат. Функцията на превръщане съществуват за такива цели.
Забележка: Има още една описание тип: той WCHAR име - това е еквивалентно на wchar_t.
TCHAR е макро за декларацията на един символ. Можете също така да декларира масив от TCHAR. Но какво, ако искате да се опише такъв характер показалка или Конст указател към героите.
Ето един пример:
След прочитане на чипове с TCHAR, може да предпочетете да го използвате. Има и добри алтернативи, които да представляват струни в кода си. За да направите това, просто завъртете Windows.h проекта.
Забележка: Ако вашият проект включва windows.h (косвено или директно), не трябва да включи в проекта TCHAR.H.
За да започне преглед на старата функция да направи по-лесно разбиране. Пример функция strlen.
Които могат да бъдат представени по различен начин.
Когато LPCSTR описан като:
LPCSTR разбира така.
• LP - Лонг Пойнт (дълга показалка)
• С - константа (константа)
• STR - String (низ)
В действителност тя LPCSTR (Long) указател към низ.
Нека да променим strcpy в съответствие с новите видове на името стил:
szTarget има вид LPSTR, без използването на видове езикови S. LPSTR се определя, както следва:
Имайте предвид, че има szSource LPCSTR тип, тъй като strcpy на функция не променят изходния буфер, така че сложи атрибут CONST. Върнатият тип данни не е постоянна низ: LPSTR.
По този начин, функцията с ул префикс да манипулира ANSI струни. Но имаме нужда от повече за двубайтови Unicode низове. За тези велики герои са еквивалентни функции.
Например, за да се изчисли дължината на герои големи символи (Unicode низ), която ще използвате wcslen:
wcslen функция прототип е както следва:
И кода по-горе могат да бъдат представени по различен начин:
Когато LPCWSTR описана както следва:
LPCWSTR може да се разбира както следва:
LP - Лонг Пойнт (дълга дръжка)
С - константа (константа)
WSTR - Wide характер String (голям низ от символи)
По същия начин, strcpy еквивалент wcscpy, за Unicode низове:
Които могат да бъдат представени като:
Когато това не е постоянна szTarget голям линия (LPWSTR) и постоянен szSource голям линия.
Има редица на еквивалентни функции за тоалетни-STR-функции. ул-функция, за да бъде използван за прости ANSI редове и тоалетни-функции за Unicode низове.
Въпреки, че вече не се препоръчват, че е необходимо да се използват естествените функции Unicode, не само ANSI или просто синтезира функция TCHAR. Причината е проста - Вашата кандидатура трябва да бъде само Unicode-Ним, и не ви е грижа за това, което sportiruyutsya за ANSI. Но за по-голяма изчерпателност Споменавам тези общ дисплей (проекция).
За да се изчисли дължината на низа, можете да използвате _tcslen функция (макро).
Която е описана по следния начин:
Когато име тип LPCTSTR може да се разбира като
LP - Лонг Пойнт (дълга дръжка)
С - константа (константа)
Т = TCHAR
STR = String (стринга)
В зависимост от настройките на проекта, LPCTSTR ще се прожектират в LPCSTR (ANSI) или LPCWSTR (Unicode).
Забележка: strlen функция или wcslen _tcslen ще се върне на броя на знака на ред, а не на брой байтове.
Общата Операция _tcscpy низ копие е описан, както следва:
Или по-генерализирана начин, като например:
Можете ли да познаете какво означава LPTSTR))
Примери за използване.
Първо даде пример за неработен код:
На ANSI монтаж, кодът компилира успешно с защото TCHAR е вид знак и името на променливата ще бъде масив от Чар. Повикване strlen да име също ще работи добре.
И така Нека се съберат едни и същи с включен UNICODE / _UNICODE (в настройките на проекта, изберете «Използване Unicode Character Set»).
Сега компилаторът ще произвежда този вид грешка:
И програмисти ще коригира грешката по следния начин:
И това не е усмири компилатора, защото преобразуването от TCHAR * в TCHAR [7] е невъзможно. Същата грешка ще се случи, когато вградените струните ANSI Unicode се предава на функцията:
За съжаление (или за щастие), тази грешка може да бъде правилно коригира чрез прости видове задействане на В.
А мислите ли, че ще се повиши нивото на техния опит при работа с указатели. Вие сте грешен код -Това ще даде грешен резултат, както и повечето от вас ще получи нарушение на достъпа (нарушение на достъп). Хвърля по този начин го като поплавък-безстепенна трансмисия, когато се очаква (логично) структурата на 80 байта.
String «Сатурн» е поредица от 7 байта:
Но когато мине един и същ набор от байтове в wcslen, той смята всеки 2 байта като един символ. Следователно, първите 2 байта [97,83], ще се разглежда като един символ, имащо стойност от 24 915 (97<<8 | 83). Это Unicode символ. И другие следующие символы рассматриваются как [117,116] и так далее.
Разбира се, вие не издържа китайски йероглифи, но отливки го направя за теб.
И така, това е много важно да се знае, че видът няма да работи. Така че за инициализация на първия ред трябва да направите следното:
Кой ще бъде излъчен на 7 или 14 байта, в зависимост от време на компилация.
Обадете wcslen трябва да бъде:
В примера по-горе, че програмният код, аз използвам strlen, което предизвиква грешки при изграждането Unicode.
Ето един пример за неработен решение за привеждане типове C език:
В Unicode възли име на променлива е с размерите на 14 байта (7 знака Unicode, включително нула). Тъй като линията
«Сатурн» съдържа само английски букви, които могат да бъдат представени с помощта на ASCII кодиране, Unicode символ "S" ще бъде представена като [83, 0]. Следващите ASCII символи се представят като нула. Забележка Сега характер "S" е представен като 2-байт стойност от 83. края на линията ще бъде представен като 2 байта, които имат стойност 0.
Така че, когато се премине низ към strlen, първия знак (т.е. първия байт) ще бъде ( "S" в случай на "Сатурн"). Но на следващия знак / байт ще бъдат идентифицирани като в края на линията. Ето защо, strlen връща неправилна стойност 1.
Както знаете, Unicode низ може да съдържа само английски букви, както и в резултат на strlen е още по-несигурно.
В кратки отливки няма да работи.
Вие ще имате, или представляват една линия в правилната форма, или да използвате функцията за конвертиране ANSI да Unicode, следват и обратно.
Сега, надявам се, че разбирате следния код:
Продължавайки темата. Вероятно сте виждали някои от функции / методи, които трябва да се предават броя на знаците, или се връща броя на символите. Но има GetCurrentDirectory, което е необходимо за предаване на броя на знаците, а не байта.
например:
От друга страна, ако трябва да се разпредели памет за желания брой знаци, че трябва да се разпределят правилно брой байтове. В C + +, можете просто да използвате оператора ново:
Но ако използвате функции за разпределение на паметта, като изчистване, LocalAlloc, GlobalAlloc и т.н. трябва да посочите броя байтове!
Както знаете, което трябва да хвърли върнатата стойност. изчистване на изразяване аргумент гарантира, че тя разпределя необходимия брой байтове - и разпределя пространство за необходимия брой знаци.
В заключение, за да се отпуснете малко мозъка си. филм цитат: "Един ден от живота на системния администратор"
Всички с NG.