Разница между MBCS и UTF-8 в Windows - PullRequest
56 голосов
/ 21 июля 2010

Я читаю о наборе символов и кодировках в Windows. Я заметил, что в компиляторе Visual Studio (для C ++) есть два флага компилятора, которые называются MBCS и UNICODE. В чем разница между ними? Что я не понимаю, так это то, как UTF-8 концептуально отличается от кодировки MBCS? Кроме того, я нашел следующую цитату в MSDN :

Unicode - это 16-битная кодировка символов

Это сводит на нет все, что я читал о Юникоде. Я думал, что Unicode может быть закодирован с различными кодировками, такими как UTF-8 и UTF-16. Может кто-нибудь пролить свет на эту путаницу?

Ответы [ 4 ]

99 голосов
/ 21 июля 2010

Я заметил, что в компиляторе Visual Studio есть два флага компилятора (для C ++), называемые 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 означает "multi-байтный набор символов ".Для ограниченного числа, кажется, что UTF-8 подойдет.

Но в Windows «MBCS» относится только к кодировкам символов, которые могут использоваться с версиями «A» функций API Windows.Это включает кодовые страницы 932 (Shift_JIS), 936 (GBK), 949 (KS_C_5601-1987) и 950 (Big5), но НЕ UTF-8.

Для использования UTF-8Вы должны преобразовать строку в UTF-16, используя MultiByteToWideChar, вызвать версию функции "W" и вызвать WideCharToMultiByte на выходе.По сути, это именно то, что на самом деле выполняют функции «А», что заставляет меня задуматься , почему Windows не просто поддерживает UTF-8 .

Эта неспособность поддерживать самый распространенный символкодировка делает «А» версию 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 была одним из первых пользователей Юникода, когда 16 бит считалось достаточным для всех, а UTF-8 использовался только в Плане 9. Так что UCS-2 был Юникод.

16 голосов
/ 22 октября 2012

_MBCS и _UNICODE - это макросы, определяющие, какую версию подпрограмм TCHAR.H вызывать. Например, если вы используете _tcsclen для подсчета длины строки, препроцессор отобразит _tcsclen в другую версию в соответствии с двумя макросами: _MBCS и _UNICODE.

_UNICODE & _MBCS Not Defined: strlen  
_MBCS Defined: _mbslen  
_UNICODE Defined: wcslen  

Чтобы объяснить разницу между этими функциями подсчета длины строки, рассмотрим следующий пример.
Если у вас есть компьютер, на котором установлена ​​версия Windows для упрощенного китайского языка, в которой используется GBK (кодовая страница 936), вы скомпилируете исходный файл в формате gbk-file и запустите его.

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 слов: 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.

10 голосов
/ 21 июля 2010

MBCS означает многобайтовый набор символов и описывает любой набор символов, в котором символ закодирован (возможно) более чем в 1 байт.

Наборы ANSI / ASCII не являются многобайтовыми.

UTF-8 , однако, являются многобайтовымикодирование.Он кодирует любой символ Unicode как последовательность из 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 голосов
/ 12 мая 2013

В качестве сноски к другим ответам в MSDN есть документ Общие текстовые сопоставления в TCHAR.H с удобными таблицами, в которых обобщено, как директивы препроцессора _UNICODE и _MBCS изменяют определение различных типов C / C ++.

Что касается фраз "Unicode" и "Multi-Byte Character Set", люди уже описали, что это за эффекты.Я просто хочу подчеркнуть, что оба из них говорят Microsoft о некоторых очень специфических вещах.(То есть они означают нечто более общее и более специфичное для Windows, чем можно было бы ожидать, если исходить из не-специфичного для Microsoft понимания интернационализации текста.) Эти точные фразы появляются и имеют тенденцию получать свои собственные отдельные разделы / подразделы.технических документов Microsoft, например, в Текст и строки в Visual C ++

...