Ce este tchar, WCHAR, LPSTR, lpwstr, lpctstr (etc.)

Ce este tchar, WCHAR, LPSTR, lpwstr, lpctstr (etc.)

Mulți programatori C ++ care scriu sub Windows este adesea confundat peste modul în care acești identificatori ciudate TCHAR, LPCTSTR. In acest articol voi încerca să cel mai bun mod de a dot I. Și ceața de îndoială.

Te întrebi.
Eu pun o pisică.

În general, caracterul șirului poate fi reprezentat ca octetul 1-lea și 2 octeți.
De obicei, un singur octet de codificare a caracterelor este ANSI- simbolul reprezentat în această codificare toate caractere englezești. Codificarea caracterelor 2-byte este UNICODE, care poate fi reprezentat de toate celelalte limbi din lume.

Visual C ++ compilator sprijină char și wchar_t ca un built-in tipurile de date și ANSI codificări UNICODE.Hotya au definiție mai specifică a Unicode, dar pentru a înțelege, acesta este un Windows utilizează codificare 2-octet pentru aplicații multiple de suport lingvistic.

Pentru a reprezenta un octet 2-Unicode utilizează o codare Microsoft Windows-UTF16.
Microsoft a devenit una dintre primele companii care au început să pună în aplicare un sprijin Unicode în sistemele lor de operare (familie de Windows NT).

Ce trebuie să faceți dacă doriți dumneavoastră C / C ++ cod pentru a fi independent de codificare și utilizarea diferitelor moduri de codificare?

TIP. Utilizați tipurile de date și nume comune pentru a reprezenta caracterele si liniile.

De exemplu, în loc de a schimba codul de mai jos:

Pentru a sprijini aplicațiile multi-lingvistice (de exemplu, Unicode), puteți scrie cod într-un mod mai general.

Setările proiectului din fila General, există un parametru care indică în ce set de caractere de codificare va compila programul:

Ce este tchar, WCHAR, LPSTR, lpwstr, lpctstr (etc.)

Dacă opțiunea «Utilizare setul de caractere Unicode», tip TCHAR va fi difuzat de tip wchar_t. Dacă «setați Utilizare caracterul multi-octet» opțiunea atunci TCHAR va fi difuzat în tipul char. Simțiți-vă liber pentru a utiliza tipurile char și wchar_t, și setările de proiect nu afectează utilizarea acestor cuvinte cheie.

TCHAR este definită după cum urmează:

_UNICODE macro este activată dacă selectați «Utilizați setul de caractere Unicode» și apoi tastați TCHAR este definit ca wchar_t. Când selectați «Utilizarea multi-octet set de caractere» TCHAR este definit ca char.

În plus, pentru ca exista suport pentru mai multe seturi de caractere, folosind o bază de cod comun, precum și capacitatea de a sprijini mai multe aplicații de limbă, folosiți funcția specifică (de exemplu, macro-uri).
In loc de a folosi strcpy, strlen, strcat (inclusiv protejate funcție de opțiuni cu _S prefix), sau wcscpy, wcslen, wcscat (inclusiv opțiuni protejate), utilizați mai bine funcția _tcscpy, _tcslen, _tcscat.

După cum știți funcția strlen este descrisă după cum urmează:

Și funcția wcslen este descrisă după cum urmează:

Mai bine utilizați _tcslen, care în mod logic, este descrisă după cum urmează:

WC-ul este un caracter larg (maior Glyph). Prin urmare, WCS funcții vor fi pentru largi caractere-string (care este, pentru un șir de caractere mari) .Such modul _tcs va însemna șir de caractere _T. Și, după cum știți șirul cu _T prefix poate fi un char sau wchar_t.

Dar, în realitate, _tcslen (și alte funcții cu _tcs prefix) nu funcționează, ea macro-uri. Ei pur și simplu descris ca fiind:

Astfel, TCHAR nu este un tip, și add-on tipurile char și wchar_t. Permițând astfel să aleagă noastre multiple voință aplicație linguală, sau toate la fel, o linguale.

Tu întrebi de ce sunt descrise ca macro-uri, dar nu ca o funcție completă.
Motivul este simplu: Biblioteca sau DLL poate exporta o funcție simplă cu același nume și prototipul (Cu excepția conceptului de suprasarcină în C ++).
De exemplu, dacă exportați o funcție:

Cum ar trebui să sun clientul ei. Cum să:

_TPrintChar magic poate fi transformată într-o funcție ce a primit două caractere octet ca argument.

Pentru a face acest lucru, vom face două funcții diferite:

Și un macro simplu va ascunde diferențele dintre ele:

Clientul solicită pur și simplu funcție ca

Rețineți că TCHAR și _TPrintChar va fi acum compatibil cu UNICODE sau ANSI, iar variabila și funcția parametrul cChar va fi comparabil cu tipul de date char sau wchar_t.

Macrocomenzi ne permit să eludeze aceste dificultăți, și ne permit să folosească funcțiile ANSI sau UNICODE pentru caractere și șiruri noastre. O mulțime de funcții specifice pentru Windows sunt descrise în acest mod, iar pentru programator are doar o funcție (de exemplu, un macro) și a fost bine.

Aici este un exemplu cu SetWindowText:

Există doar câteva funcții în care nu există o astfel de macro-uri, și numai cu W sau sufix A. Un exemplu al acestei funcții ReadDirectoryChangesW, care nu are echivalent în codificarea ANSI.

După cum știți, vom folosi ghilimele pentru a reprezenta siruri de caractere. Șirul furnizat în acest mod este ANSI-string, fiecare caracter folosește 1 octet. Iată un exemplu:

Acest top a liniei nu este un UNICODE șir, și nu este potrivit pentru un sprijin în mai multe limbi. În scopul de a obține șir de caractere UNICODE ar trebui să folosiți prefixul L.
Iată un exemplu:

Așezați L din față și veți obține un șir de caractere UNICODE. Toate caracterele (repet, toate caracterele) este de 2 octeți, inclusiv litere englezești, spații, numere și caracterul nul. Cantitatea de date șir Unicode va fi întotdeauna un multiplu al doilea octet. de caractere șir Unicode de lungime 7 ar ocupa 14 octeți. Dacă șirul Unicode este de 15 octeți, atunci nu este linia corectă, și nu va funcționa în orice context.

De asemenea, linia va fi un multiplu de sizeof dimensiune (TCHAR) în octeți.

Când aveți nevoie de un cod de hard-codificate, puteți scrie cod de genul:

Linia fără prefix este un șir de caractere ANSI, prefixat cu șir L Unicode, iar șirul cu _T prefix și compilarea dependente TEXT. Din nou și TEXT _T macro-l din nou. Acestea sunt definite după cum urmează:

Simbolul ## este cheia (jeton) se introduce declarația care se va transforma _T ( «Unicode») în L «Unicode», în cazul în care șirul este un argument pentru makrosa- excepția cazului în care _UNICODE determinat.
În cazul în care nu _UNICODE definit _T ( «Unicode») face în «Unicode». Cheia declarație insera a existat chiar și în limbajul C, și nu este un lucru specific asociat cu siruri de caractere codificate în VC ++.

Pentru mai multe informații, macro-uri pot fi aplicate nu numai pentru siruri de caractere, ci și pentru personaje. De exemplu, _T ( 'R') este la rândul său, L'R 'sau, într-un' R“. Adică, fie la caracterul Unicode sau ANSI.

Nu, și nu din nou, nu puteți utiliza un macro pentru a converti un caracter sau șir de caractere în text Unicode și non-Unicode.
Codul de mai jos este greșit:

_T rând (c); _T (str); Compile mod fin ANSI, _T (x) devine, în x, și _T (c) împreună cu _T (str), se va transforma într-o c și str.
Dar atunci când construi proiectul în modul Unicode, codul nu este compilat cu:

N-aș vrea să provoace un accident vascular cerebral, inteligența ta, și să explice de ce nu funcționează.

Există mai multe funcții de conversie siruri de caractere Mulbaytovyh în UNICODE, pe care le voi spune în curând.

Există un punct important, aproape toate funcțiile pe care ia un șir de caractere sau un simbol, o prioritate în Windows API, au numele generic de MSDN și în altă parte.
SetWindowTextA funcția / W vor fi clasificate ca:

Dar, după cum știți, este macro doar SetWindowText, și în funcție de setările proiectului vor fi considerate ca fiind:

Biblioteca User32.dll, există 2 funcții SetWindowTextA SetWindowTextW și care sunt exportate, care este, nu există nici un nume cu numele generic.

Toate funcțiile care au atât versiunea ANSI și UNICODE, au de fapt doar implementarea UNICODE. Acest lucru înseamnă că, atunci când apelați SetWindowTextA din codul dvs., care trece șirul de parametri ANSI - acesta convertește ANSI la UNICODE este SetWindowTextW.
Un loc de muncă reală (setare din titlu / numele / eticheta ferestrei) face doar versiunea Unicode!

Luați un alt exemplu, care va primi fereastra de text utilizând GetWindowText.
Suni GetWindowTextA dându-i ANSI tampon ca tampon de destinație.
GetWindowTextA provoca mai întâi GetWindowTextW, memorie, eventual, alocând pentru șiruri Unicode (adică o wchar_t matrice).
El convertește apoi Unicode ANSI șir pentru tine.

Aceste ANSI la conversie Unicode nu este limitat numai funcții GUI, precum și rularea tuturor subsetul funcției API Windows care are un șir de caractere și are două opțiuni.
Aici este un alt exemplu de astfel de funcții:

Prin urmare, este recomandat pentru a apela în mod direct funcțiile Unicode.
La rândul său, acest lucru înseamnă că ar trebui să fie întotdeauna axat pe asamblarea versiunii Unicode, mai degrabă decât versiunea ANSI a ansamblului, având în vedere faptul că sunteți obișnuiți să utilizați siruri de caractere ANSI de ani de zile.

Da, aveți posibilitatea să salvați și primiți un șir de ANSI, cum ar fi scris într-un fișier, sau pot trimite mesaje instant chat-program. Funcția de conversie există pentru astfel de scopuri.

Notă: Nu există un alt tip de descriere: nume WCHAR-l - este echivalent cu wchar_t.

TCHAR este un macro pentru declararea unui singur caracter. Puteți declara, de asemenea, o serie de TCHAR. Dar ce se întâmplă dacă doriți să descrie un astfel de indicator de caractere sau un pointer const la caracterele.
Iată un exemplu:

Dupa ce a citit chips-uri cu TCHAR, s-ar putea prefera să-l folosească. Există, de asemenea, alternative bune pentru a reprezenta siruri de caractere în codul. Pentru a face acest lucru, pur și simplu rândul său, Windows.h proiectului.
Notă: În cazul în care proiectul include windows.h (indirect sau direct), ar trebui să nu includă în proiectul TCHAR.H.
Pentru a lansa o revizuire a funcției vechi pentru a face mai ușor de înțeles. Funcția EXEMPLUL strlen.

Care poate fi reprezentat în mod diferit.

În cazul în care LPCSTR descris ca fiind:

LPCSTR a înțeles acest lucru.
• LP - lung pointer (indicator lung)
• C - Constant (constant)
• STR - String (șir de caractere)
De fapt, LPCSTR (lung) pointer la un șir de caractere.

Să schimbăm strcpy în conformitate cu noile tipuri de nume de stil:

szTarget are tip LPSTR, fără utilizarea unor tipuri de limbaj S. LPSTR este definită după cum urmează:

Rețineți că szSource are tip LPCSTR, deoarece funcția strcpy nu modifică buffer-sursă, astfel încât a pus const atribut. Tipul de date returnat nu este un șir constant: LPSTR.

Astfel, funcția cu str prefixul pentru a manipula siruri de caractere ANSI. Dar avem nevoie de mai mult de doi octeți siruri de caractere Unicode. Pentru aceste caractere mari sunt funcții echivalente.
De exemplu, pentru a calcula lungimea de caractere de caractere mari (Unicode șir), veți utiliza wcslen:

Funcția wcslen prototip este după cum urmează:

Și codul de mai sus pot fi reprezentate în mod diferit:

În cazul în care LPCWSTR descrisă după cum urmează:

LPCWSTR poate fi înțeleasă după cum urmează:
LP - Pointer lung (mâner lung)
C - Constant (constant)
WSTR - șir de caractere lat (șir mare de caractere)

În mod similar, strcpy wcscpy echivalent, pentru siruri de caractere Unicode:

Care poate fi reprezentat ca:

În cazul în care acest lucru nu este constantă szTarget linie de mare (LPWSTR), și constantă szSource linie de mare.

Există o serie de funcții echivalente pentru WCS-Str-funcții. str-funcția de a folosi rânduri ANSI simple și WCS-funcții pentru siruri de caractere Unicode.

Deși am sfătuit deja că este necesar să se utilizeze funcții Unicode native, nu numai ANSI sau doar sintetizat funcția TCHAR. Motivul este simplu - cererea dumneavoastră ar trebui să fie doar Unicode-NYM, și nu le pasă de ceea ce au sportiruyutsya pentru ANSI. Dar, pentru motive de exhaustivitate, menționez aceste afișare comun (proiecție).

Pentru a calcula lungimea șirului, puteți utiliza funcția _tcslen (macro).
Care este descrisă după cum urmează:

În cazul în care numele de tip LPCTSTR poate fi înțeleasă ca
LP - Pointer lung (mâner lung)
C - Constant (constant)
T = TCHAR
STR = String (String)

În funcție de setările de proiect, LPCTSTR vor fi proiectate în LPCSTR (ANSI) sau LPCWSTR (Unicode).

Notă: Funcția strlen, sau wcslen _tcslen va returna numărul de caractere pe linie, mai degrabă decât numărul de octeți.

Operation Generalized copie string _tcscpy este descrisă după cum urmează:

Sau mai generalizate mod, cum ar fi:

Poți ghici ce înseamnă LPTSTR))

Exemple de utilizare.

da mai întâi un exemplu de cod non-de lucru:

Pe ANSI de asamblare, codul compilează cu succes, deoarece TCHAR este un tip de char, iar numele variabilei va fi o matrice de char. Apelarea strlen pentru a numi, de asemenea, va funcționa bine.

Deci Să ne compila același lucru cu UNICODE inclus / _UNICODE (în setările de proiect, selectați «Utilizare setul de caractere Unicode»).
Acum, compilatorul va produce acest tip de eroare:

Iar programatorii vor corecta eroarea în acest fel:

Și nu e pacifica compilator, deoarece conversia de la TCHAR * în TCHAR [7] este imposibil. Aceeași eroare va apărea atunci când built-in siruri de caractere ANSI Unicode sunt transmise la funcția:

Din păcate (sau din fericire), această eroare poate fi corectată în mod corespunzător de către un simplu tipuri de acționare C.

Și crezi că va ridica nivelul experienței lor atunci când se lucrează cu indicii. Greșiți -Acest cod va da rezultatul greșit, și cele mai multe dintre voi va primi violare de acces (acces violare). Mulaje astfel ca transmisia float variabilă atunci când așteptat (logic) structura de 80 de octeți.

Șirul «Saturn» este o secvență de octeți 7:

Dar atunci când treci același set de octeți în wcslen, el consideră că fiecare 2 octeți ca un singur caracter. De aceea, primele 2 octeți [97.83] va fi considerat ca un simbol având o valoare de 24915 (97<<8 | 83). Это Unicode символ. И другие следующие символы рассматриваются как [117,116] и так далее.

Desigur, nu a trecut caracterele chinezești, dar mulaje face acest lucru pentru tine.
Și de aceea este foarte important să se știe că tipul nu va funcționa. Deci, pentru inițializarea primei linii ar trebui să faceți următoarele:

Care va fi difuzat la 7 sau 14 biți, în funcție de timpul compilării.
Call wcslen ar trebui să fie:

În exemplul de mai sus codul programului, folosesc strlen, care cauzează erori în construi Unicode.
Aici este un exemplu de soluție care nu de lucru pentru a aduce tipurile limbajului C:

În Unicode ansambluri nume variabilă este dimensiunea de 14 octeți (7 caractere unicode, inclusiv null). Deoarece linia
«Saturn» conține numai caractere englezești care pot fi reprezentate utilizând codarea ASCII, simbolul Unicode „S“ va fi prezentat ca [83, 0]. Următoarele caractere ASCII sunt reprezentate ca fiind zero. Notă Acum caracterul „S“ este reprezentat ca o valoare de 2 octeți de 83. Sfârșitul liniei va fi reprezentat ca 2 octeți având o valoare de la 0.

Deci, atunci când treci un șir de caractere la strlen, primul caracter (de exemplu, primul octet) ar fi ( „S“, în cazul „Saturn“). Dar următorul caracter / octet va fi identificat ca fiind capătul liniei. Prin urmare, strlen returnează o valoare incorectă 1.

După cum știți, Unicode șir poate conține numai caractere englezești, iar rezultatul strlen este chiar mai nesigură.

În mulaje scurte nu va funcționa.
Vei avea, sau reprezintă o linie în forma corectă, sau utilizați funcția de conversie ANSI în Unicode, urmați și înapoi.

Acum, sper să înțelegeți următorul cod:

Continuând tema. Ați văzut, probabil, unele dintre funcțiile / metodele pe care trebuie să le transmită numărul de caractere, sau returnează numărul de caractere. Dar există GetCurrentDirectory, care este necesară pentru a transmite numărul de caractere, nu bytes.
exemplu:

Pe de altă parte, în cazul în care aveți nevoie pentru a aloca memorie pentru numărul de caractere dorit trebuie să aloce numărul adecvat de octeți. În C + +, puteți utiliza pur și simplu operatorul nou:

Dar, dacă utilizați funcțiile de alocare de memorie, cum ar fi malloc, LocalAlloc, GlobalAlloc, etc. trebuie să specificați numărul de octeți!

După cum știți că aveți nevoie să arunce valoarea de returnare. Malloc Argumentul de expresie asigură că alocă numărul necesar de octeți - și alocă spațiu pentru numărul necesar de caractere.

În concluzie, să se relaxeze puțin creierul. Citat film, „O zi din viața administratorului de sistem“
Toate NG.