Różnica między MBCS i UTF-8 W Windows
Czytam o zestawie charater i kodowaniu w Windows. Zauważyłem, że w kompilatorze Visual Studio (dla C++) są dwie flagi kompilatora o nazwie MBCS i UNICODE. Jaka jest między nimi różnica ? Nie rozumiem, jak UTF-8 różni się koncepcyjnie od kodowania MBCS ? Ponadto znalazłem następujący cytat w MSDN:
Unicode jest 16-bitowym kodowaniem znaków
To neguje to, co czytałem o Unicode. Myślałem, że unicode może być kodowane różnymi kodowaniami, takimi jak UTF-8 i UTF-16. Czy ktoś może rzucić więcej światła na to zamieszanie?
4 answers
Zauważyłem, że istnieją dwa Kompilatory flagi w kompilatorze Visual Studio (dla C++) o nazwie MBCS i UNICODE. Co to jest różnica między nimi ?
Wiele funkcji w Windows API jest dostępnych w dwóch wersjach: jedna, która pobiera parametry char
(na stronie kodowej) i jedna, która pobiera parametry wchar_t
(w UTF-16).
int MessageBoxA(HWND hWnd, const char* lpText, const char* lpCaption, unsigned int uType);
int MessageBoxW(HWND hWnd, const wchar_t* lpText, const wchar_t* lpCaption, unsigned int uType);
Każda z tych par funkcji ma również makro bez przyrostka, które zależy od tego, czy makro UNICODE
jest zdefiniowany.
#ifdef UNICODE
#define MessageBox MessageBoxW
#else
#define MessageBox MessageBoxA
#endif
Aby to zadziałało, typ TCHAR
jest zdefiniowany tak, aby wyodrębnić typ znaków używany przez funkcje API.
#ifdef UNICODE
typedef wchar_t TCHAR;
#else
typedef char TCHAR;
#endif
To jednak był zły pomysł. Zawsze należy wyraźnie określić typ znaku.
To czego nie rozumiem to jak jest UTF-8 koncepcyjnie różni się od MBCS kodowanie ?
MBCS oznacza "multi-bajtowy zestaw znaków". Dla dosłownych, wydaje się, że UTF-8 / align = "left" /
Ale w systemie Windows "MBCS" odnosi się tylko do kodowania znaków, które mogą być używane z wersjami" A " funkcji Windows API. Obejmuje To strony kodowe 932 (Shift_JIS), 936 (GBK), 949 (KS_C_5601-1987) i 950 (Big5), ale Nie} UTF-8.
Aby użyć UTF-8, musisz przekonwertować łańcuch znaków na UTF-16 za pomocą MultiByteToWideChar
, wywołać wersję "W" funkcji i wywołać WideCharToMultiByte
na wyjściu. To jest zasadniczo to, co funkcje "A" faktycznie zrobić, co sprawia, że zastanawiam się dlaczego Windows nie obsługuje tylko UTF-8.
Unicode jest 16-bitowym kodowaniem znaków
To neguje to, co przeczytałem o Unicode.
MSDN się myli. Unicode to 21-bitowy kodowany zestaw znaków, który ma kilka kodowań, najbardziej UTF-8, UTF-16 i UTF-32. (Istnieją również inne kodowania Unicode, takie jak GB18030, UTF-7 i UTF-EBCDIC.)
Gdy Microsoft odnosi się do "Unicode", tak naprawdę oznacza UTF-16 (lub UCS-2). Dzieje się tak ze względów historycznych. Windows NT był wczesnym użytkownikiem Unicode, kiedy uważano, że 16 bitów wystarczy dla wszystkich, a UTF-8 był używany tylko na planie 9. Więc UCS-2 był Unicode.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:25:34
_MBCS i _UNICODE są makrami określającymi, która wersja TCHAR.H100000000000 Na przykład, jeśli użyjesz _tcsclen
do policzenia długości łańcucha, preprocesor zmapuje _tcsclen
do innej wersji zgodnie z dwoma makrami: _MBCS i _UNICODE.
_UNICODE & _MBCS Not Defined: strlen
_MBCS Defined: _mbslen
_UNICODE Defined: wcslen
Aby wyjaśnić różnicę między tymi funkcjami liczenia długości łańcucha, rozważ poniższy przykład.
Jeśli masz komputer z systemem Windows Simplified Chinese edition, który używa GBK (936 code page), kompilujesz plik źródłowy zakodowany gbk i uruchom go.
printf("%d\n", _mbslen((const unsigned char*)"I爱你M"));
printf("%d\n", strlen("I爱你M"));
printf("%d\n", wcslen((const wchar_t*)"I爱你M"));
Wynik będzie 4 6 3
.
Oto szesnastkowa reprezentacja I爱你M
w GBK.
GBK: 49 B0 AE C4 E3 4D 00
_mbslen wie, że ten łańcuch jest zakodowany w GBK, więc może poprawnie go odtworzyć i uzyskać właściwy wynik 4
słowa: 49
jako I
, B0 AE
jako 爱
, C4 E3
jako 你
, 4D
jako M
.
Strlen wie tylko 0x00
, więc dostaje 6
.
Wcslen rozważ, że tablica hexdeciaml jest zakodowana w UTF16LE i liczy dwa bajty jako jedno słowo, więc otrzymuje 3
słowa: 49 B0
, AE C4
, E3 4D
.
Jak zauważył @xiaokaoy, jedynym poprawnym terminatorem dla wcslen
jest 00 00
. Tak więc wynik nie jest gwarantowany 3
, Jeśli następujący bajt nie jest 00
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-12 13:19:10
MBCS oznacza wielobajtowy zestaw znaków i opisuje dowolny zestaw znaków, w którym znak jest zakodowany w (ewentualnie) więcej niż 1 bajt.
ANSI / ASCII zestawy znaków nie są wielobajtowe.
UTF-8 jest kodowaniem wielobajtowym. Koduje dowolny znak Unicode jako sekwencję 1, 2, 3 lub 4 oktety (bajty).
UTF-8 jest jednak tylko jednym z kilku możliwych konkretnych kodowań Unicode zestaw znaków. UTF-16 jest innym kodowaniem używanym przez Windows/. NET (IIRC). Oto różnica między UTF-8 a UTF-16:
UTF-8 koduje dowolny znak Unicode jako sekwencję 1, 2, 3 lub 4 bajtów.
UTF-16 koduje większość znaków Unicode jako 2 bajty, a niektóre jako 4 bajty.
Jest zatem nie poprawne, że Unicode jest 16-bitowym kodowaniem znaków. To raczej coś w rodzaju 21-bitowego kodowania (a nawet więcej w dzisiejszych czasach), ponieważ obejmuje zestaw znaków z punktami kodu U+000000
do U+10FFFF
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-21 11:33:36
Jako przypis do innych odpowiedzi, MSDN ma dokument Generic-Text Mappings w TCHAR.H z przydatnymi tabelami podsumowującymi sposób, w jaki dyrektywy preprocesora _UNICODE i _MBCS zmieniają definicję różnych typów C/C++.
Jeśli chodzi o wyrażenia "Unicode" i "Multi-bajtowy zestaw znaków", ludzie już opisali, jakie są efekty. Chcę tylko podkreślić, że oba te rozwiązania są bardzo specyficzne dla Microsoftu. (Czyli oznaczają coś mniej ogólnego i bardziej specyficzny dla systemu Windows, niż można by się spodziewać, jeśli pochodzi z innego niż Microsoft rozumienia internacjonalizacji tekstu.) Te dokładne zwroty pojawiają się i mają tendencję do uzyskiwania osobnych sekcji / podrozdziałów dokumentów technicznych microsoft, np. w tekst i ciągi w Visual C++
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-10 20:31:09