Diferencia entre MBCS y UTF-8 en Windows

Estoy leyendo sobre el conjunto de charater y las codificaciones en Windows. Noté que hay dos indicadores de comstackción en el comstackdor de Visual Studio (para C ++) llamados MBCS y UNICODE. Cuál es la diferencia entre ellos ? Lo que no entiendo es cómo UTF-8 es conceptualmente diferente de una encoding MBCS. Además, encontré la siguiente cita en MSDN :

Unicode es una encoding de caracteres de 16 bits

Esto niega todo lo que leo sobre el Unicode. Pensé que Unicode puede codificarse con diferentes codificaciones, como UTF-8 y UTF-16. ¿Alguien puede arrojar más luz sobre esta confusión?

Noté que hay dos indicadores de comstackción en el comstackdor de Visual Studio (para C ++) llamados MBCS y UNICODE. Cuál es la diferencia entre ellos ?

Muchas funciones de la API de Windows vienen en dos versiones: una que toma los parámetros char (en una página de códigos específica de la configuración regional) y otra que toma los parámetros wchar_t (en 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); 

Cada uno de estos pares de funciones también tiene una macro sin el sufijo, que depende de si se define la macro UNICODE .

 #ifdef UNICODE #define MessageBox MessageBoxW #else #define MessageBox MessageBoxA #endif 

Para que esto funcione, el tipo de TCHAR se define para abstraer el tipo de carácter utilizado por las funciones de la API.

 #ifdef UNICODE typedef wchar_t TCHAR; #else typedef char TCHAR; #endif 

Esto, sin embargo, fue una mala idea . Siempre debe especificar explícitamente el tipo de carácter.

Lo que no entiendo es cómo UTF-8 es conceptualmente diferente de una encoding MBCS.

MBCS significa “juego de caracteres multibyte”. Para los de mente literal, parece que UTF-8 calificaría.

Pero en Windows, “MBCS” solo se refiere a las codificaciones de caracteres que se pueden usar con las versiones “A” de las funciones de la API de Windows. Esto incluye las páginas de códigos 932 (Shift_JIS), 936 (GBK), 949 (KS_C_5601-1987) y 950 (Big5), pero NO UTF-8.

Para usar UTF-8, debe convertir la cadena a UTF-16 usando MultiByteToWideChar , llamar a la versión “W” de la función y llamar a WideCharToMultiByte en la salida. Esto es esencialmente lo que hacen las funciones “A”, lo que me hace preguntarme por qué Windows no solo admite UTF-8 .

Esta incapacidad para admitir la encoding de caracteres más común hace que la versión “A” de la API de Windows sea inútil. Por lo tanto, siempre debe usar las funciones “W” .

Unicode es una encoding de caracteres de 16 bits

Esto niega todo lo que leo sobre el Unicode.

MSDN está equivocado. Unicode es un conjunto de caracteres codificados de 21 bits que tiene varias codificaciones, siendo las más comunes UTF-8, UTF-16 y UTF-32. (También hay otras codificaciones Unicode, como GB18030, UTF-7 y UTF-EBCDIC).

Cada vez que Microsoft se refiere a “Unicode”, realmente quieren decir UTF-16 (o UCS-2). Esto es por razones históricas. Windows NT fue uno de los primeros en adoptar Unicode, cuando se pensaba que 16 bits eran suficientes para todos, y UTF-8 solo se utilizaba en el Plan 9. Por lo tanto, UCS-2 era Unicode.

_MBCS y _UNICODE son macros para determinar qué versión de rutinas TCHAR.H llamar. Por ejemplo, si usa _tcsclen para contar la longitud de una cadena, el preprocesador _tcsclen a una versión diferente de acuerdo con las dos macros: _MBCS y _UNICODE.

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

Para explicar la diferencia de estas funciones de conteo de longitud de cuerda, considere el siguiente ejemplo.
Si tiene un cuadro de equipo que ejecuta la edición de Windows Simplified Chinese que usa GBK (página de códigos 936), comstack un archivo fuente codificado en archivo gbk y lo ejecuta.

 printf("%d\n", _mbslen((const unsigned char*)"I爱你M")); printf("%d\n", strlen("I爱你M")); printf("%d\n", wcslen((const wchar_t*)"I爱你M")); 

El resultado sería 4 6 3 .

Aquí está la representación hexadecimal de I爱你M en GBK.

 GBK: 49 B0 AE C4 E3 4D 00 

_mbslen sabe que esta cadena está codificada en GBK, por lo que podría interpretar la cadena correctamente y obtener el resultado correcto de 4 palabras: 49 como I , B0 AE como , C4 E3 como , 4D como M

strlen solo sabe 0x00 , entonces obtiene 6 .

wcslen considera que esta matriz de hexdeciaml está codificada en UTF16LE, y cuenta dos bytes como una palabra, por lo que obtiene 3 palabras: 49 B0 , AE C4 , E3 4D .

como señaló @xiaokaoy, el único terminador válido para wcslen es 00 00 . Por lo tanto, no se garantiza que el resultado sea 3 si el siguiente byte no es 00 .

MBCS significa conjunto de caracteres de múltiples bytes y describe cualquier conjunto de caracteres donde un carácter está codificado en (posiblemente) más de 1 byte.

Los juegos de caracteres ANSI / ASCII no son multibyte.

UTF-8 , sin embargo, es una encoding de múltiples bytes. Codifica cualquier carácter Unicode como una secuencia de 1, 2, 3 o 4 octetos (bytes).

Sin embargo, UTF-8 es solo una de varias posibles codificaciones concretas del juego de caracteres Unicode. En particular, UTF-16 es otra, y pasa a ser la encoding utilizada por Windows / .NET (IIRC). Aquí está la diferencia entre UTF-8 y UTF-16:

  • UTF-8 codifica cualquier carácter Unicode como una secuencia de 1, 2, 3 o 4 bytes.

  • UTF-16 codifica la mayoría de los caracteres Unicode como 2 bytes, y algunos como 4 bytes.

Por lo tanto, no es correcto que Unicode sea una encoding de caracteres de 16 bits. Es más bien algo así como una encoding de 21 bits (o incluso más estos días), ya que abarca un conjunto de caracteres con puntos de código U+000000 hasta U+10FFFF .

Como nota al pie de las otras respuestas, MSDN tiene un documento Generic-Text Mappings en TCHAR.H con prácticas tablas que resumen cómo las directivas de preprocesador _UNICODE y _MBCS cambian la definición de diferentes tipos de C / C ++.

En cuanto al fraseo “Unicode” y “Juego de caracteres de múltiples bytes”, las personas ya han descrito cuáles son los efectos. Solo quiero enfatizar que ambos son palabras de Microsoft para algunas cosas muy específicas. (Es decir, se refieren a algo menos general y más particular a Windows de lo que uno esperaría si proviene de una comprensión no específica de Microsoft de la internacionalización de texto). Esas frases exactas aparecen y tienden a tener sus propias secciones / subsecciones de documentos técnicos de Microsoft, por ejemplo, en texto y cadenas en Visual C ++