literal compiler c++ unicode c++11

compiler - c++17



¿A qué codificación se convierte c32rtomb? (3)

Como lo probé, en Linux / MacOSX, c32rtomb convierte cadenas de UTF-32 a las codificaciones específicas del entorno local. Puede usar nl_langinfo (CODESET) para obtener la codificación utilizada actualmente.

Sin embargo, libc usa la configuración regional "C" de forma predeterminada, que utiliza ISO-8859-1 como la codificación. Para cambiar la codificación que especifica el entorno del sistema, generalmente UTF-8 pero que puede ser otra, use setlocale (LC_CTYPE, "").

En Windows, VS2015 +, sin embargo, c32rtomb siempre se convierte a UTF-8. Dado que vcruntime no admite las configuraciones regionales UTF-8 (solo se admiten las configuraciones locales ANSI / OEM heredadas), si sigue el estándar, c32rtomb / c16rtomb sería totalmente idéntico a wcrtomb, y no tendrá ningún uso.

Las funciones c32rtomb y mbrtoc32 de <cuchar> / <uchar.h> se describen en el C Unicode TR ( draft ) al realizar conversiones entre UTF-32 1 y "caracteres multibyte".

(...) Si s no es un puntero nulo, la función c32rtomb determina el número de bytes necesarios para representar el carácter multibyte que corresponde al carácter ancho dado por c32 (incluidas las secuencias de desplazamiento), y almacena la representación del carácter multibyte en la matriz cuyo primer elemento es señalado por s . (...)

¿Qué es esta "representación de caracteres multibyte"? Estoy realmente interesado en el comportamiento del siguiente programa:

#include <cassert> #include <cuchar> #include <string> int main() { std::u32string u32 = U"this is a wide string"; std::string narrow = "this is a wide string"; std::string converted(1000, ''/0''); char* ptr = &converted[0]; std::mbstate_t state {}; for(auto u : u32) { ptr += std::c32rtomb(ptr, u, &state); } converted.resize(ptr - &converted[0]); assert(converted == narrow); }

¿Se garantiza que la afirmación contenida es 1 ?

1 Trabajando bajo el supuesto de que __STDC_UTF_32__ está definido.


El TR vinculado en la pregunta dice

En la mayoría de los MB_CUR_MAX se almacenan los bytes.

que se define (en C99) como

una expresión entera positiva con el size_t que es el número máximo de bytes en un carácter multibyte para el conjunto de caracteres extendido especificado por la configuración regional actual

Creo que esto es suficiente evidencia de que la intención del TR era producir los caracteres multibyte según lo definido por la configuración regional C actualmente instalada: UTF-8 para en_US.utf8 , GB18030 para zh_CN.gb18030 , etc.


Para garantizar que la afirmación sea cierta, es necesario que la codificación multibyte utilizada por c32rtomb() sea ​​la misma que la codificación utilizada para los literales de cadena, al menos en lo que respecta a los caracteres realmente utilizados en la cadena.

C99 7.11.1.1/2 especifica que setlocale() con la categoría LC_CTYPE afecta el comportamiento de las funciones de manejo de caracteres y las funciones multibyte y de caracteres anchos. No veo ningún reconocimiento explícito de que el efecto sea establecer las codificaciones de caracteres multibyte y ancho utilizadas, sin embargo, esa es la intención.

Por lo tanto, la codificación multibyte utilizada por c32rtomb() es la codificación multibyte de la configuración regional predeterminada "C".

C ++ 11 2.14.3 / 2 especifica que la codificación de ejecución, la codificación de ejecución amplia, UTF-16 y UTF-32 se utilizan para los literales de caracteres y cadenas correspondientes. Por lo tanto, std::string narrow utiliza la codificación de ejecución para representar esa cadena.

Entonces, ¿la codificación de configuración local "C" de esta cadena es la misma que la codificación de ejecución de esta cadena?

C99 7.11.1.1/3 especifica que la configuración regional "C" proporciona "el entorno mínimo" para la traducción de C. Dicho entorno incluiría no solo los juegos de caracteres, sino también los códigos de caracteres específicos utilizados. Así que creo que esto significa no solo que la configuración regional "C" debe admitir los caracteres requeridos en la traducción (es decir, el conjunto de caracteres básico), sino que además esos caracteres en la configuración regional "C" deben usar los mismos códigos de caracteres.

Todos los caracteres en sus literales de cadena son miembros del conjunto de caracteres básico y, por lo tanto, la conversión de la representación char32_t a la representación de la configuración regional "C" debe producir la misma secuencia de valores que el compilador produce para el literal de la cadena char ; la afirmación debe ser cierta.

No veo ninguna sugerencia de que cualquier cosa más allá del conjunto de caracteres básico sea compatible de una manera compatible entre la codificación de ejecución y la configuración regional "C", por lo que si su cadena literal utiliza caracteres fuera del conjunto de caracteres básico, entonces no habrá ninguna. Garantizamos que la afirmación se mantendría. Incluso estipulando caracteres extendidos que existen tanto en el conjunto de caracteres de ejecución como en la configuración regional "C", no veo ningún requisito de que las representaciones coincidan entre sí.