xc3 xb3 error coding codigo codificacion caracteres c++ utf-8 c++11 ascii c11

c++ - xb3 - use ñ in python



¿Por qué no hay un literal de caracteres ASCII o UTF-8 en C11 o C++ 11? (5)

Como saben, los caracteres codificados en UTF-8 necesitan varios octetos, por lo tanto, los caracteres s, por lo que el tipo natural para ellos es char[] , ¡que de hecho es el tipo para un literal de cadena u8 u8! Así que C11 está bien encaminado aquí, solo que se adhiere a sus convenciones de sintaxis usando " para una cadena , que necesita ser utilizado como una matriz de caracteres, en lugar de su propuesta semántica implícita para usar '' lugar.

Acerca de "0" frente a u8"0" , está leyendo correctamente, solo se garantiza que este último es idéntico a { 0x30, 0 } , incluso en sistemas EBCDIC. Por cierto, el hecho mismo de lo primero no se puede manejar convenientemente en su código, si presta atención al __STDC_MB_MIGHT_NEQ_WC__ identificador predefinido.

¿Por qué no hay un literal de caracteres UTF-8 en C11 o C ++ 11 a pesar de que hay literales de cadena UTF-8? Entiendo que, en términos generales, un literal de carácter representa un único carácter ASCII que es idéntico a un punto de código UTF-8 de un solo octeto, pero ni C ni C ++ dicen que la codificación debe ser ASCII.

Básicamente, si leo el derecho estándar, no hay garantía de que ''0'' represente el entero 0x30, pero u8"0" debe representar la secuencia char 0x30 0x00.

EDITAR:

Soy consciente de que no todos los puntos de código UTF-8 cabrían en un char. Tal literal solo sería útil para los puntos de código de un solo octeto (también conocido como ASCII), así que supongo que llamarlo "literal de carácter ASCII" sería más apropiado, por lo que la pregunta sigue en pie. Simplemente elegí encuadrar la pregunta con UTF-8 porque hay literales de cadena UTF-8. La única forma en que puedo imaginarme de forma portátil garantizando los valores ASCII sería escribir una constante para cada personaje, lo cual no sería tan malo considerando que solo hay 128, pero aún así ...


El literal de caracteres UTF-8 tendría que tener una longitud variable; para la mayoría de ellos, no es posible almacenar un solo carácter en char o wchar , ¿qué tipo debería tener, entonces? Como no tenemos tipos de longitud variable en C, ni en C ++, a excepción de las matrices de tipos de tamaño fijo, el único tipo razonable sería const char * - y se requiere que las cadenas C terminen en nulo, por lo que No cambies nada.

En cuanto a la edición:

Cita del estándar C ++ 11:

Los glifos para los miembros del conjunto de caracteres de origen básico están destinados a identificar los caracteres del subconjunto de ISO / CEI 10646 que corresponde al conjunto de caracteres ASCII. Sin embargo, debido a que la asignación de los caracteres del archivo de origen al conjunto de caracteres de origen (descrito en la fase de traducción 1) se define como definida por la implementación, se requiere una implementación para documentar cómo se representan los caracteres de origen básicos en los archivos de origen.

(nota a pie de página en 2.3.1).

Creo que es una buena razón para no garantizarlo. Aunque, como anotó en el comentario aquí, para la mayoría (o todos) los compiladores principales, el ASCII-ness de caracteres literales está garantizado en la implementación.


Es perfectamente aceptable escribir código C no portátil, y esta es una de las muchas buenas razones para hacerlo. Siéntase libre de asumir que su sistema utiliza ASCII o algún superconjunto del mismo, y advierta a sus usuarios que no deben intentar ejecutar su programa en un sistema EBCDIC.

Si te sientes muy generoso, puedes codificar un cheque. Se gperf programa gperf genera código que incluye dicha comprobación.

_Static_assert(''0'' == 48, "must be ASCII-compatible");

O, para compiladores pre-C11,

extern int must_be_ascii_compatible[''0'' == 48 ? 1 : -1];

Si está en C11, puede usar el prefijo u o U en las constantes de caracteres, pero no el prefijo u8 ...

/* This is useless, doesn''t do what you want... */ _Static_assert(0, "this code is broken everywhere"); if (c == ''々'') ... /* This works as long as wchar_t is UTF-16 or UTF-32 or UCS-2... */ /* Note: you shouldn''t be using wchar_t, though... */ _Static_assert(__STDC_ISO_10646__, "wchar_t must be some form of Unicode"); if (c == L''々'') ... /* This works as long as char16_t is UTF-16 or UCS-2... */ _Static_assert(__STDC_UTF_16__, "char16_t must be UTF-16"); if (c == u''々'') ... /* This works as long as char32_t is UTF-32... */ _Static_assert(__STDC_UTF_32__, "char32_t must be UTF-32"); if (c == U''々'') ...

Hay algunos proyectos que están escritos en C muy portátil y se han portado a sistemas que no son ASCII ( example ). Esto requirió una cantidad no trivial de esfuerzo de transferencia, y no hay ninguna razón real para hacer el esfuerzo a menos que sepa que desea ejecutar su código en sistemas EBCDIC.

Sobre los estándares: las personas que escriben el estándar de C tienen que lidiar con todas las implementaciones de C posibles, incluso algunas bastante extrañas. Hay sistemas conocidos donde sizeof(char) == sizeof(long) , CHAR_BIT != 8 , los tipos integrales tienen representaciones de trampas, sizeof(void *) != sizeof(int *) , sizeof(void *) != sizeof(void (*)()) , va_list se va_list montón, etc. Es una pesadilla.

No se gane por intentar escribir código que se ejecute en sistemas de los que nunca haya oído hablar, y no busque las garantías en el estándar C.

Por ejemplo, en lo que respecta al estándar C, la siguiente es una implementación válida de malloc :

void *malloc(void) { return NULL; }

Tenga en cuenta que si u8"..." constantes u8"..." tienen la garantía de ser UTF-8, u"..." y U"..." no tienen garantías, excepto que la codificación es de 16 bits y 32 bits por carácter, respectivamente , y la codificación real debe estar documentada por la implementación.

Resumen: Es seguro asumir la compatibilidad con ASCII en 2012.


Para C ++, esto se ha abordado en el número 119 de Evolution Working Group: Agregar literales de u8 caracteres cuya sección de Motivación dice:

Tenemos cinco prefijos de codificación para literales de cadena (ninguno, L, u8, u, U) pero solo cuatro para literales de caracteres; el que falta es u8. Si el conjunto de caracteres de ejecución restringida no es ASCII, los literales de u8 de caracteres proporcionarán una forma de escribir literales de caracteres con codificación ASCII garantizada (las codificaciones de u8 de unidad de código único son exactamente ASCII). Agregar soporte para estos literales agregaría una característica útil y haría el lenguaje un poco más consistente.

EWG discutió la idea de agregar literales de u8 caracteres en Rapperswil y aceptó el cambio. Este documento proporciona una redacción para esa extensión.

Esto se incorporó en el borrador de trabajo utilizando la redacción de N4267: Agregando literales de u8 caracteres y podemos encontrar la redacción en este momento, el último borrador de la norma N4527 y observe que la sección 2.14.3 dice que están limitadas a los puntos de código que encajan en una sola Unidad de código UTF-8:

Un literal de caracteres que comienza con u8, como u8''w '', es un literal de caracteres de tipo char, conocido como literal de caracteres UTF-8. El valor de un literal de caracteres UTF-8 es igual a su valor de punto de código ISO10646, siempre que el valor del punto de código sea representable con una sola unidad de código UTF-8 (es decir, siempre que sea un carácter US-ASCII). Un literal de caracteres UTF-8 que contiene múltiples c-caracteres está mal formado.


Si no confía en que su compilador tratará ''0'' como el carácter ASCII 0x30, entonces podría usar static_cast<char>(0x30) lugar.