Разница между MBCS и UTF-8 в Windows
Я читаю о наборе charator и кодировках в Windows. Я заметил, что в компиляторе Visual Studio есть два флага компилятора (для С++) под названием MBCS и UNICODE. В чем разница между ними? Я не понимаю, как UTF-8 концептуально отличается от кодирования MBCS? Кроме того, я нашел следующую цитату в MSDN:
Unicode - это 16-разрядная кодировка символов
Это отрицает все, что я читал о Unicode. Я думал, что unicode может быть закодирован с различными кодировками, такими как UTF-8 и UTF-16. Может кто-то пролил еще немного света на эту путаницу?
Ответы
Ответ 1
Я заметил, что есть два компилятора флаги в компиляторе Visual Studio (для С++) называется MBCS и UNICODE. Что разница между ними?
Многие функции в API Windows входят в две версии: один, который принимает параметры char
(на кодовой странице, специфичной для локали), и одну, которая принимает параметры wchar_t
(в 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);
Каждая из этих пар функций также имеет макрос без суффикса, который зависит от того, определен ли макрос UNICODE
.
#ifdef UNICODE
#define MessageBox MessageBoxW
#else
#define MessageBox MessageBoxA
#endif
Для выполнения этой работы тип TCHAR
определяется для абстрагирования символьного типа, используемого функциями API.
#ifdef UNICODE
typedef wchar_t TCHAR;
#else
typedef char TCHAR;
#endif
Это, однако, было плохой идеей. Вы всегда должны явно указывать тип символа.
Я не понимаю, как UTF-8 концептуально отличается от MBCS кодирование?
MBCS означает "многобайтовый набор символов". Для буквального мышления кажется, что UTF-8 будет квалифицироваться.
Но в Windows "MBCS" относится только к кодировке символов, которая может использоваться с "A" версиями функций Windows API. Это включает в себя кодовые страницы 932 (Shift_JIS), 936 (GBK), 949 (KS_C_5601-1987) и 950 (Big5), но NOT UTF-8.
Чтобы использовать UTF-8, вам нужно преобразовать строку в UTF-16 с помощью MultiByteToWideChar
, вызвать версию функции W и вызвать WideCharToMultiByte
на выходе. Фактически это то, что на самом деле выполняют функции "А", что заставляет меня задаться вопросом почему Windows не просто поддерживает UTF-8.
Эта неспособность поддерживать наиболее распространенную кодировку символов делает "A" версию Windows API бесполезной. Поэтому вы должны всегда использовать функции "W" .
Unicode - это 16-разрядная кодировка символов
Это отрицает все, что я читал о Unicode.
MSDN ошибочна. Unicode - это 21-битный кодированный набор символов, который имеет несколько кодировок, наиболее распространенными из которых являются UTF-8, UTF-16 и UTF-32. (Существуют и другие кодировки Unicode, такие как GB18030, UTF-7 и UTF-EBCDIC.)
Всякий раз, когда Microsoft ссылается на "Unicode", они действительно означают UTF-16 (или UCS-2). Это по историческим причинам. Windows NT была ранней последовательностью Unicode, когда 16 бит считалось достаточно для всех, а UTF-8 использовался только на Plan 9. Таким образом, UCS-2 был Unicode.
Ответ 2
_MBCS и _UNICODE - это макросы, чтобы определить, какую версию подпрограмм TCHAR.H вызывать. Например, если вы используете _tcsclen
для подсчета длины строки, препроцессор будет сопоставлять _tcsclen
с другой версией в соответствии с двумя макросами: _MBCS и _UNICODE.
_UNICODE & _MBCS Not Defined: strlen
_MBCS Defined: _mbslen
_UNICODE Defined: wcslen
Чтобы объяснить разницу этих функций подсчета длины строки, рассмотрите следующий пример.
Если у вас есть компьютерный ящик, который запускает упрощенную китайскую версию Windows, использующую GBK (кодовая страница 936), вы компилируете исходный файл с кодировкой gbk файла и запускаете его.
printf("%d\n", _mbslen((const unsigned char*)"I爱你M"));
printf("%d\n", strlen("I爱你M"));
printf("%d\n", wcslen((const wchar_t*)"I爱你M"));
Результат будет 4 6 3
.
Вот шестнадцатеричное представление I爱你M
в GBK.
GBK: 49 B0 AE C4 E3 4D 00
_mbslen знает, что эта строка закодирована в GBK, поэтому она может правильно интерпретировать строку и получить правильный результат 4
words: 49
как I
, B0 AE
как 爱
, C4 E3
как 你
, 4D
как M
.
strlen знает только 0x00
, поэтому он получает 6
.
wcslen считает, что этот массив hexdeciaml закодирован в UTF16LE, и он считает два байта одним словом, поэтому он получает слова 3
: 49 B0
, AE C4
, E3 4D
.
как указал @xiaokaoy, единственным допустимым терминатором для wcslen
является 00 00
. Таким образом, результат не гарантирован быть 3
, если следующий байт не равен 00
.
Ответ 3
MBCS означает Многобайтовый набор символов и описывает любой набор символов, в котором символ кодируется (возможно) более 1 байт.
Символьные наборы ANSI/ ASCII не являются многобайтовыми.
UTF-8, однако, является многобайтовой кодировкой. Он кодирует любой символ Юникода в виде последовательности из 1, 2, 3 или 4 октетов (байтов).
Однако UTF-8 является лишь одним из нескольких возможных конкретных кодировок набора символов Unicode. Примечательно, что UTF-16 является другим, и, случается, это кодировка, используемая Windows/.NET(IIRC). Здесь разница между UTF-8 и UTF-16:
-
UTF-8 кодирует любой символ Unicode как последовательность из 1, 2, 3 или 4 байта.
-
UTF-16 кодирует большинство символов Unicode как 2 байта, а некоторые - как 4 байта.
Поэтому неверно, что Unicode является 16-разрядной кодировкой символов. Это скорее нечто вроде 21-битной кодировки (или даже больше в наши дни), поскольку она включает набор символов с кодовыми точками U+000000
до U+10FFFF
.
Ответ 4
В качестве примечания к другим ответам, MSDN имеет документ Сопоставление общих текстов в TCHAR.H с удобными таблицами, в которых показано, как инструкции препроцессора _UNICODE и _MBCS изменяют определение различных типов C/С++.
Что касается формулировки "Unicode" и "Multi-Byte Character Set", люди уже описали, что такое эффекты. Я просто хочу подчеркнуть, что оба из них - Microsoft - говорят о некоторых очень специфических вещах. (То есть они означают что-то менее общее и более специфичное для Windows, чем можно было бы ожидать, если бы оно исходило из не-Microsoft-понимания интернационализации текста.) Эти точные фразы появляются и имеют тенденцию получать свои отдельные разделы/подразделы технических документов Microsoft, например в Текст и строки в Visual С++