entendiendo c-‘0 ‘

Estaba intentando probar una de las funciones de K&R que usa c-‘0 ‘. Para entender claramente escribí un código de dos líneas como abajo. Mi pregunta es por qué está imprimiendo “1”. Y qué significa realmente el “valor numérico” en este contexto. ¡Gracias!

char c = 'a'; printf("%c",c-'0'); 

c - '0' solo tiene un valor específico definido cuando c es un dígito (‘0’, ‘1’, … o ‘9’).

Cuando c es '0' , '0' - '0' es 0 porque son iguales cuando c es '1' , '1' - '0' es 1 porque '1' sigue inmediatamente '0' en cualquier conjunto de caracteres La implementación de C elige utilizar. Lo mismo para '2' y los otros dígitos: '9' - '0' tiene un valor de 9 .

Y realmente no debería imprimir un valor con el especificador de formato "%c" .

El valor numérico es el valor ASCII del carácter.

'a' es 97, '0' es 48. 97-48 = 49.

49, a su vez, es el valor de '1' , así que eso es lo que se imprime.

Los caracteres en C no son más que un valor entero. Su valor se define de acuerdo con una encoding de caracteres . La encoding ASCII es muy conocida y la que se aplica a la pregunta publicada por el OP. Por lo tanto, ‘0’ es igual a 48 y ‘a’ es igual a 97. Al restarlos, solo está obteniendo la diferencia entre esos caracteres en la tabla ASCII.

En este ejemplo (equivalente al tuyo):

 printf("%c",'a'-'0'); 

obtienes 1 desde 97-48 = 49 que corresponde al carácter ASCII ‘1’.

Si, en cambio, estaba usando (tenga en cuenta “% d” en lugar de “% c”):

 printf("%d",'a'-'0'); 

Entonces esto solo imprimirá la diferencia (49 en este caso), y no el carácter ASCII asociado a la diferencia.

El comportamiento de su código depende de la implementación. Se basa en la encoding de caracteres.

En mi máquina Linux, el carácter a está codificado en ASCII (y en UTF8) como el byte único 97 (decimal), es decir, 0x61 . Del mismo modo, el carácter 0 se codifica como 48 es decir, 0x30 . La diferencia 'a' - '0' es 97 - 48 que es 49 que es la encoding del carácter 1

En algunas máquinas EBCDIC antiguas (p. Ej., Mainframes IBM antiguos, o en otras nuevas que se ejecutan en algún modo de compatibilidad o sistema operativo), la encoding es diferente.

Con UTF8 (ahora se usa con mucha frecuencia) existen muchos más caracteres (por ejemplo, la C cedilla ç para la ortografía francesa), ¡y generalmente están codificados en más de un byte!

c – ‘0’ restará el código de carácter de ‘0’ (48) de c. Si c representa un dígito, esto resultará en el valor numérico correspondiente a c (3 para el carácter ‘3’ por ejemplo).

Aún para obtener este valor numérico, debe utilizar el especificador de formato% d en printf en lugar de% c.

No tiene mucho sentido restar ‘0’ de ‘a’ pero quizás tenga alguna aplicación para una tarea en particular.

Vamos a explicar esto un poco más usando números enteros en lugar de caracteres.

 char c = 97; printf("%d", c - 48); 

Esto, por supuesto, imprimirá 49, pero a medida que lo traducimos en caracteres con la tabla ASCII obtenemos 1.

 char c = 97; printf("%c", c-48); 

Este código ahora imprime 1 porque usamos el tipo de datos char cuando imprimimos y convierte el valor 49 en el número ASCII equivalente 1.

Para probar esto podemos probar algo como esto.

 char a = 'a'; char b = 97; if((a == b) && ((a-'0') == (b-48))) { printf("%s", "true"); } 

Primero vemos si a y b son equivalentes y luego vemos si a-‘0 ‘es equivalente a b-48. Como ambas son ciertas, imprimimos la verdad.

El carácter dentro de comillas simples, como ‘0’, es una constante de carácter. Es una constante numérica dependiendo del conjunto de caracteres de la máquina. En el conjunto de caracteres ASCII, ‘a’ es equivalente a 97 y ‘0’ es 48.

97-48 = 49, que es equivalente a ‘1’ en el conjunto de caracteres ASCII. Al final, se imprimirá ‘1’ en formato% c.