Подтвердить что ты не робот

Разница между MBCS и UTF-8 в Windows

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

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

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

4b9b3361

Ответ 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 С++