numeral letras lenguaje funciona especiales completo como codigos codigo circulo caracteres c++ c ascii

letras - ¿C y C++ garantizan el ASCII de los caracteres[af] y[AF]?



como funciona el codigo ascii (3)

Estoy viendo el siguiente código para probar un dígito hexadecimal y convertirlo en un entero. El código es bastante inteligente, ya que aprovecha la diferencia entre mayúsculas y minúsculas: 32, y eso es el bit 5. Por lo tanto, el código realiza un OR adicional, pero guarda un JMP y dos CMP s.

static const int BIT_FIVE = (1 << 5); static const char str[] = "0123456789ABCDEFabcdef"; for (unsigned int i = 0; i < COUNTOF(str); i++) { int digit, ch = str[i]; if (ch >= ''0'' && ch <= ''9'') digit = ch - ''0''; else if ((ch |= BIT_FIVE) >= ''a'' && ch <= ''f'') digit = ch - ''a'' + 10; ... }

¿C y C ++ garantizan el ASCII o los valores de los caracteres [af] y [AF]? Aquí, garantía significa que los conjuntos de caracteres superior e inferior siempre diferirán en un valor constante que se puede representar con un bit (para el truco anterior). Si no, ¿qué dice la norma sobre ellos?

(Lo siento por la etiqueta C y C ++. Me interesa la posición de ambos idiomas sobre el tema).


No hay garantías sobre los valores particulares, pero no debería importarle, ya que su software probablemente nunca encontrará un sistema que no sea compatible de esta manera con ASCII. Supongamos que el espacio siempre es 32 y que A siempre es 65, esto funciona bien en el mundo moderno.

El estándar C solo garantiza que las letras AZ y az existen y que caben dentro de un solo byte.

Esto garantiza que 0-9 son secuenciales.

Tanto en la fuente como en los juegos de caracteres básicos, el valor de cada carácter después de 0 en la lista anterior de dígitos decimales será uno mayor que el valor del anterior.

Justificación

Hay muchas codificaciones de caracteres en el mundo. Si le importa la portabilidad, puede hacer que su programa sea portátil a diferentes conjuntos de caracteres, o puede elegir un conjunto de caracteres para usar en cualquier lugar (por ejemplo, Unicode). Seguiré adelante y categorizaré libremente la mayoría de las codificaciones de caracteres existentes para ti:

  1. Codificaciones de caracteres de un solo byte compatibles con ISO / IEC 646. Los dígitos 0-9 y las letras AZ y az siempre ocupan las mismas posiciones.

  2. Codificaciones de caracteres multibyte (Big5, Shift JIS, basadas en ISO 2022). En estas codificaciones, su programa probablemente ya está roto y tendrá que dedicar tiempo a arreglarlo si le importa. Sin embargo, los números de análisis seguirán funcionando como se esperaba.

  3. Codificaciones Unicode. Los dígitos 0-9 y las letras AZ, siempre ocupan las mismas posiciones. Puede trabajar con puntos de código o unidades de código libremente y obtendrá el mismo resultado, si está trabajando con puntos de código por debajo de 128 (que usted es). (¿Trabaja con UTF-7? No, solo debe usar eso para correo electrónico.

  4. EBCDIC. A los dígitos y las letras se les asignan valores diferentes a sus valores en ASCII, sin embargo, 0-9 y AF, af siguen siendo contiguos. Incluso entonces, la posibilidad de que su código se ejecute en un sistema EBCDIC es esencialmente cero.

Entonces, la pregunta aquí es: ¿Cree que una quinta opción hipotética se inventará en el futuro, de alguna manera menos compatible / más difícil de usar que Unicode?

¿Te importa EBCDIC?

Podríamos imaginar sistemas extraños todo el día ... supongamos que CHAR_BIT es 11, o sizeof(long) = 100 , o supongamos que usamos la aritmética del complemento, o malloc() siempre devuelve NULL , o supongamos que los píxeles de su monitor están ordenados Una rejilla hexagonal. Suponga que sus números de punto flotante no son IEEE 754, suponga que todos sus punteros de datos son de diferentes tamaños. Al final del día, esto no nos acerca a nuestros objetivos de escribir software en funcionamiento en sistemas modernos reales (con la excepción ocasional ).


No, no lo hace.

El estándar C garantiza que existen los dígitos decimales y las letras mayúsculas y minúsculas, junto con una serie de otros caracteres. También garantiza que los dígitos decimales son contiguos, por ejemplo ''0'' + 9 == ''9'' , y que todos los miembros del conjunto de caracteres de ejecución básicos tienen valores no negativos. Específicamente no garantiza que las letras sean contiguas. (Para todos los detalles sangrientos, vea el borrador N1570 del estándar C, sección 5.2.1; la garantía de que los caracteres básicos no son negativos se encuentra en 6.2.5p3, en la discusión de tipo char ).

El supuesto de que ''a'' .. ''f'' y ''A'' .. ''F'' tienen códigos contiguos es casi seguro que es razonable. En ASCII y en todos los juegos de caracteres basados ​​en ASCII, las 26 letras minúsculas son contiguas, al igual que las 26 letras mayúsculas. Incluso en EBCDIC , el único rival significativo para ASCII, el alfabeto en su conjunto no es contiguo, pero las letras ''a'' .. ''f'' y ''A'' .. ''F'' son (EBCDIC tiene espacios entre ''i'' y ''j'' , entre ''r'' y ''s'' , entre ''I'' y ''J'' , y entre ''R'' y ''S'' ).

Sin embargo, la suposición de que establecer el bit 5 de la representación convertirá las letras mayúsculas en minúsculas no es válida para EBCDIC. En ASCII, los códigos para las letras minúsculas y mayúsculas difieren en 32; en EBCDIC difieren por 64.

Este tipo de cambio de bits para guardar una instrucción o dos puede ser razonable en el código que forma parte de la biblioteca estándar o que se sabe que es crítico para el rendimiento. La suposición implícita de un conjunto de caracteres basado en ASCII debería IMHO al menos ser explícita por un comentario. Una tabla de búsqueda estática de 256 elementos probablemente sería incluso más rápida a expensas de una pequeña cantidad de almacenamiento adicional.


Para una máxima portabilidad, claridad y velocidad, sugeriría un simple interruptor:

int hex_digit_value(char x) { switch (x) { case ''0'': return 0; case ''1'': return 1; case ''2'': return 2; case ''3'': return 3; case ''4'': return 4; case ''5'': return 5; case ''6'': return 6; case ''7'': return 7; case ''8'': return 8; case ''9'': return 9; case ''A'': case ''a'': return 10; case ''B'': case ''b'': return 11; case ''C'': case ''c'': return 12; case ''D'': case ''d'': return 13; case ''E'': case ''e'': return 14; case ''F'': case ''f'': return 15; default: return -1; } }

clang -O1 -S transforma esto en una búsqueda de tabla simple:

addl $-48, %edi cmpl $54, %edi ja .LBB0_2 movslq %edi, %rax movl .Lswitch.table(,%rax,4), %eax retq .LBB0_2: movl $-1, %eax retq

Para completar, aquí está la tabla de búsqueda generada:

.Lswitch.table: .long 0 # 0x0 .long 1 # 0x1 .long 2 # 0x2 .long 3 # 0x3 .long 4 # 0x4 .long 5 # 0x5 .long 6 # 0x6 .long 7 # 0x7 .long 8 # 0x8 .long 9 # 0x9 .long 4294967295 # 0xffffffff .long 4294967295 # 0xffffffff .long 4294967295 # 0xffffffff .long 4294967295 # 0xffffffff .long 4294967295 # 0xffffffff .long 4294967295 # 0xffffffff .long 4294967295 # 0xffffffff .long 10 # 0xa .long 11 # 0xb .long 12 # 0xc .long 13 # 0xd .long 14 # 0xe .long 15 # 0xf .long 4294967295 # 0xffffffff .long 4294967295 # 0xffffffff .long 4294967295 # 0xffffffff .long 4294967295 # 0xffffffff .long 4294967295 # 0xffffffff .long 4294967295 # 0xffffffff .long 4294967295 # 0xffffffff .long 4294967295 # 0xffffffff .long 4294967295 # 0xffffffff .long 4294967295 # 0xffffffff .long 4294967295 # 0xffffffff .long 4294967295 # 0xffffffff .long 4294967295 # 0xffffffff .long 4294967295 # 0xffffffff .long 4294967295 # 0xffffffff .long 4294967295 # 0xffffffff .long 4294967295 # 0xffffffff .long 4294967295 # 0xffffffff .long 4294967295 # 0xffffffff .long 4294967295 # 0xffffffff .long 4294967295 # 0xffffffff .long 4294967295 # 0xffffffff .long 4294967295 # 0xffffffff .long 4294967295 # 0xffffffff .long 4294967295 # 0xffffffff .long 4294967295 # 0xffffffff .long 10 # 0xa .long 11 # 0xb .long 12 # 0xc .long 13 # 0xd .long 14 # 0xe .long 15 # 0xf