Jestem nowy w programowaniu Windows i po przeczytaniu książki Petzolda zastanawiam się:
czy nadal dobrą praktyką jest używanie TCHAR
typu i _T()
funkcji do deklarowania ciągów, czy też powinienem używać po prostu ciągów wchar_t
i L""
w nowym kodzie?
Skoncentruję się tylko na systemie Windows 2000 i nowszych, a mój kod od samego początku będzie i18n .
Krótka odpowiedź: NIE .
Jak wszyscy inni już napisali, wielu programistów nadal używa TCHAR i odpowiadających im funkcji. Moim skromnym zdaniem cała koncepcja była złym pomysłem . Przetwarzanie napisów UTF-16 znacznie różni się od prostego przetwarzania łańcuchów ASCII / MBCS. Jeśli używasz tych samych algorytmów / funkcji z obiema z nich (na tym opiera się idea TCHAR!), Uzyskasz bardzo złą wydajność w wersji UTF-16, jeśli robisz coś więcej niż zwykłą konkatenację ciągów (np. parsowanie itp.). Głównym powodem są Surogaty .
Z jedynym wyjątkiem, kiedy naprawdę musisz skompilować swoją aplikację dla systemu, który nie obsługuje Unicode, nie widzę powodu, aby wykorzystywać ten bagaż z przeszłości w nowej aplikacji.
źródło
TCHAR
nie powinno być już używane, nie zgadzam się, że to był zły pomysł. Uważam również, że jeśli zdecydujesz się być wyraźny zamiast używaćTCHAR
, powinieneś być wyraźny wszędzie . To znaczy nie używaj funkcji zTCHAR
/_TCHAR
(takimi jak_tmain
) w ich deklaracji. Krótko mówiąc: bądź konsekwentny. +1, nadal.TCHAR
początkowo wprowadzono: Aby ułatwić tworzenie kodu dla wersji Windows opartych na Windows 9x i Windows NT. W tamtym czasie implementacją UTF-16 w Windows NT była UCS-2, a algorytmy analizy / manipulacji na ciągach znaków były identyczne. Nie było żadnych surogatów. Nawet w przypadku surogatów algorytmy DBCS (jedyne obsługiwane kodowanie MBCS dla systemu Windows) i UTF-16 są takie same: w każdym kodowaniu punkt kodowy składa się z jednej lub dwóch jednostek kodu.Muszę się zgodzić z Saschą. Podstawowym założeniem
TCHAR
/_T()
/ etc. jest to, że możesz napisać aplikację opartą na "ANSI", a następnie w magiczny sposób nadać jej obsługę Unicode poprzez zdefiniowanie makra. Ale opiera się to na kilku złych założeniach:Aktywnie budujesz oprogramowanie w wersji MBCS i Unicode
W przeciwnym razie będą ślizgać się i używać zwykłych
char*
ciągów w wielu miejscach.Że w literałach _T ("...") nie używasz znaków z ukośnikiem odwrotnym spoza ASCII
O ile Twoim kodowaniem „ANSI” nie jest ISO-8859-1, wynikowe
char*
iwchar_t*
literały nie będą reprezentować tych samych znaków.Te ciągi UTF-16 są używane tak jak ciągi „ANSI”
Oni nie są. Unicode wprowadza kilka koncepcji, które nie istnieją w większości starszych kodowań znaków. Surogaty. Łączenie znaków. Normalizacja. Reguły wielkości liter warunkowych i zależnych od języka.
I być może najważniejsze, fakt, że UTF-16 rzadko jest zapisywany na dysku lub przesyłany przez Internet: UTF-8 jest preferowany do reprezentacji zewnętrznej.
Twoja aplikacja nie korzysta z Internetu
(To może być prawidłowe założenie dla twojego oprogramowania, ale ...)
Sieć działa na UTF-8 i wielu rzadszych kodowaniach .
TCHAR
Koncepcja uznaje tylko dwa: "ANSI" (które nie mogą być UTF-8 ) i "Unicode" (UTF-16). Może to być przydatne do wykonywania wywołań interfejsu API systemu Windows z obsługą Unicode, ale jest cholernie bezużyteczne, aby aplikacje internetowe i e-mailowe obsługiwały Unicode.Że nie używasz bibliotek innych niż Microsoft
Nikt inny nie używa
TCHAR
. Poco używastd::string
i UTF-8. SQLite ma wersje UTF-8 i UTF-16 swojego API, ale nieTCHAR
.TCHAR
nie ma go nawet w standardowej bibliotece, więc nie,std::tcout
chyba że chcesz to zdefiniować samodzielnie.Co polecam zamiast TCHAR
Zapomnij, że istnieją kodowania „ANSI”, z wyjątkiem sytuacji, gdy musisz odczytać plik, który nie jest prawidłowym UTF-8. Zapomnij o tym
TCHAR
. Zawsze wywołuj wersję „W” funkcji Windows API.#define _UNICODE
tylko po to, aby upewnić się, że przypadkowo nie wywołasz funkcji „A”.Zawsze używaj kodowania UTF dla łańcuchów: UTF-8 dla
char
łańcuchów i UTF-16 (w systemie Windows) lub UTF-32 (w systemach typu Unix) dlawchar_t
łańcuchów.typedef
UTF16
iUTF32
typy postaci, aby uniknąć różnic między platformami.źródło
#define _UNICODE
. Koniec transmisji :)_UNICODE
kontroluje, w jaki sposób mapowania tekstu ogólnego są rozwiązywane w CRT. Jeśli nie chcesz wywoływać wersji ANSI interfejsu API systemu Windows, musisz zdefiniowaćUNICODE
.Jeśli zastanawiasz się, czy nadal jest w praktyce, to tak - nadal jest dość często używany. Nikt nie będzie wyglądał śmiesznie na Twój kod, jeśli używa on TCHAR i _T („”). Projekt, nad którym teraz pracuję, konwertuje z ANSI na Unicode - i wybieramy trasę przenośną (TCHAR).
Jednak...
Moim głosem byłoby zapomnieć o wszystkich przenośnych makrach ANSI / UNICODE (TCHAR, _T ("") i wszystkie wywołania _tXXXXXX, itp ...) i po prostu założyć unicode wszędzie. Naprawdę nie widzę sensu bycia przenośnym, jeśli nigdy nie będziesz potrzebować wersji ANSI. Użyłbym bezpośrednio wszystkich funkcji i typów szerokich znaków. Preprend wszystkie literały łańcuchowe za pomocą L.
źródło
Artykuł Wprowadzenie do programowania w systemie Windows w witrynie MSDN mówi
Trzymałbym się
wchar_t
iL""
.źródło
Chciałbym zasugerować inne podejście (żadne z dwóch).
Podsumowując, użyj char * i std :: string, zakładając kodowanie UTF-8 i wykonuj konwersje do UTF-16 tylko podczas zawijania funkcji API.
Więcej informacji i uzasadnienie tego podejścia w programach systemu Windows można znaleźć pod adresem http://www.utf8everywhere.org .
źródło
TCHAR
/WCHAR
może wystarczyć w przypadku niektórych starszych projektów. Ale w przypadku nowych aplikacji powiedziałbym NIE .Wszystkie te
TCHAR
/WCHAR
rzeczy są tam ze względów historycznych.TCHAR
zapewnia pozornie schludny sposób (przebranie) przełączania między kodowaniem tekstu ANSI (MBCS) a kodowaniem tekstu Unicode (UTF-16). W przeszłości ludzie nie rozumieli liczby znaków we wszystkich językach świata. Założyli, że 2 bajty wystarczą do reprezentowania wszystkich znaków, a tym samym mają schemat kodowania znaków o stałej długości przy użyciuWCHAR
. Jednak po wydaniu Unicode 2.0 w 1996 roku nie jest to już prawdą .To znaczy: Bez względu na to, którego używasz w
CHAR
/WCHAR
/TCHAR
, część przetwarzania tekstu w twoim programie powinna być w stanie obsłużyć znaki o zmiennej długości do internacjonalizacji.Więc faktycznie musisz zrobić więcej niż wybranie jednego z
CHAR
/WCHAR
/TCHAR
do programowania w Windows:WCHAR
. Ponieważ w ten sposób łatwiej jest pracować z WinAPI z obsługą Unicode.Sprawdź tę wspaniałą stronę internetową, aby uzyskać bardziej szczegółowe informacje: http://utf8everywhere.org/
źródło
Tak, absolutnie; przynajmniej dla makra _T. Nie jestem jednak taki pewien, jeśli chodzi o rzeczy o szerokim charakterze.
Powodem jest lepsza obsługa WinCE lub innych niestandardowych platform Windows. Jeśli masz 100% pewności, że twój kod pozostanie w systemie NT, prawdopodobnie możesz po prostu użyć zwykłych deklaracji łańcucha C. Jednak najlepiej jest skłaniać się ku bardziej elastycznemu podejściu, ponieważ znacznie łatwiej #definiować to makro na platformie innej niż Windows w porównaniu z przeglądaniem tysięcy wierszy kodu i dodawaniem go wszędzie na wypadek, gdyby trzeba było przenieść jakąś bibliotekę do Windows Mobile.
źródło
IMHO, jeśli w twoim kodzie są TCHARs, pracujesz na złym poziomie abstrakcji.
Podczas przetwarzania tekstu używaj dowolnego typu ciągu, który jest dla Ciebie najwygodniejszy - mam nadzieję, że będzie to coś, co obsługuje Unicode, ale to zależy od Ciebie. W razie potrzeby wykonaj konwersję na granicach interfejsu OS API.
W przypadku ścieżek do plików utwórz własny typ niestandardowy zamiast używać ciągów. Pozwoli to na niezależne od systemu operacyjnego separatory ścieżek, zapewni łatwiejszy interfejs do kodowania niż ręczne łączenie i dzielenie ciągów i będzie o wiele łatwiejsze do dostosowania do różnych systemów operacyjnych (ansi, ucs-2, utf-8, cokolwiek) .
źródło
Jedyne powody, dla których widzę, aby używać czegokolwiek innego niż jawne WCHAR, to przenośność i wydajność.
Jeśli chcesz, aby Twój ostateczny plik wykonywalny był jak najmniejszy, użyj funkcji char.
Jeśli nie zależy Ci na wykorzystaniu pamięci RAM i chcesz, aby internacjonalizacja była tak łatwa, jak proste tłumaczenie, użyj WCHAR.
Jeśli chcesz, aby Twój kod był elastyczny, użyj TCHAR.
Jeśli planujesz używać tylko znaków łacińskich, równie dobrze możesz użyć ciągów ASCII / MBCS, aby użytkownik nie potrzebował tak dużej ilości pamięci RAM.
Osoby, które są „i18n od samego początku”, mogą zaoszczędzić miejsce na kod źródłowy i po prostu korzystać ze wszystkich funkcji Unicode.
źródło
Dodam tylko do starego pytania:
NIE
Rozpocznij nowy projekt CLR C ++ w VS2010. Microsoft sami używają
L"Hello World"
”- powiedział nuff.źródło
C
iC++
. Odpowiedzi mogą zawsze zostać usunięte przez ich autorów. To byłby dobry moment na skorzystanie z tego przepisu.TCHAR
mają nowe znaczenie do przenoszenia zWCHAR
doCHAR
.https://docs.microsoft.com/en-us/windows/uwp/design/globalizing/use-utf8-code-page
źródło