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


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

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

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

4 53

4 ответа:

я заметил, что есть два компилятора флаги в компиляторе Visual Studio (для В C++) называется многобайтовых кодировок и Unicode. Что в чем разница между ними ?

многие функции в Windows API поставляются в двух версиях: одна, которая принимает 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);

каждая из этих пар функций также имеет макрос без суффикса, который зависит от того, является ли макрос.

#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 концептуально отличается от МБК кодирование ?

кодировка расшифровывается как "многобайтных символов набор." Для буквального мышления, похоже, что 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 на выходе. Это по существу то, что на самом деле делают функции" A", что заставляет меня задаться вопросом почему Windows не просто поддерживает UTF-8.

это неспособность поддерживать наиболее распространенная кодировка символов делает версию" A " API Windows бесполезной. Поэтому вы должны всегда используйте функции "W".

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

это перечеркивает все, что я читал о Юникод.

MSDN ошибается. Unicode-это 21-битный кодированный набор символов, который имеет несколько кодировок, наиболее распространенными из которых являются UTF-8, UTF-16 и UTF-32. (Существуют и другие кодировки Юникода, такие как GB18030, UTF-7 и UTF-EBCDIC.)

всякий раз, когда Microsoft ссылается на "Unicode", они действительно означают UTF-16 (или UCS-2). Это по историческим причинам. Windows NT был ранним последователем Unicode, когда считалось, что 16 бит достаточно для всех, а UTF-8 использовался только по плану 9. Так что UCS-2 был Unicode.

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

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

чтобы объяснить разницу этих функций подсчета длины строк, рассмотрим следующий пример.
Если у вас есть компьютер, который работает под управлением Windows Simplified Chinese edition, которые используют 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.

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

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

UTF-8, однако, является многобайтовой кодировки. Он кодирует любой символ Юникода в виде последовательности 1, 2, 3, или 4 октета (байта).

однако UTF-8-это только один из несколько возможных конкретных кодировок набора символов Unicode. Примечательно, что UTF-16-это еще одна кодировка, используемая Windows / .NET (IIRC). Вот разница между UTF-8 и UTF-16:

  • UTF-8 кодирует любой символ Юникода в виде последовательности 1, 2, 3, или 4 байта.

  • UTF-16 кодирует большинство символов Юникода как 2 байта, а некоторые как 4 байта.

поэтому не исправить этот Юникод является 16-битной кодировкой символов. Это скорее что-то вроде 21-битной кодировки (или даже больше в наши дни), поскольку она включает в себя набор символов с кодовыми точками U+000000 до U+10FFFF.

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

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