reemplazar - ¿Por qué el comportamiento de restar caracteres a la implementación es específico?
reemplazar caracteres de una cadena c# (3)
Esta declaración:
if(''z'' - ''a'' == 25)
No se garantiza evaluar de la misma manera. Es dependiente del compilador. Además, no se garantiza que se evalúe de la misma manera que esto:
#if ''z'' - ''a'' == 25
incluso si tanto el preprocesador como el compilador se ejecutan en la misma máquina. ¿Porqué es eso?
El OP solicita una cotización directa de la norma - N1570 §6.10.1p3.4 + nota al pie 168 :
... la expresión constante de control se evalúa de acuerdo con las reglas de 6.6. ... Esto incluye interpretar constantes de caracteres, que pueden implicar convertir secuencias de escape en miembros del conjunto de caracteres de ejecución. Si el valor numérico para estas constantes de caracteres coincide con el valor obtenido cuando se produce una constante de caracteres idénticos en una expresión (que no sea dentro de una directiva #if o #elif) está definido por la implementación. 168
[nota al pie 168] Por lo tanto, la expresión constante en la siguiente directiva #if y si la declaración no garantiza evaluar el mismo valor en estos dos contextos.
#if ''z'' - ''a'' == 25 if (''z'' - ''a'' == 25)
Entonces, sí, realmente no está garantizado.
Para comprender por qué no está garantizado, primero debe saber que el estándar C no requiere que las constantes de caracteres ''a''
y ''z''
tengan los valores numéricos asignados a esos caracteres por ASCII. Hoy en día, la mayoría de las implementaciones de C utilizan ASCII o un superconjunto, pero existe otra codificación llamada EBCDIC que todavía se usa ampliamente (solo en mainframes de IBM, pero todavía hay muchos de ellos). En EBCDIC, no solo ''a''
y ''z''
tienen valores diferentes de ASCII, ¡el alfabeto no es una secuencia contigua! Es por eso que la expresión ''z'' - ''a'' == 25
podría no ser verdadera en primer lugar.
También debe saber que el estándar C intenta mantener una distinción entre la codificación de texto utilizada para el código fuente (el "conjunto de caracteres de origen") y la codificación de texto que el programa utilizará en tiempo de ejecución (el "conjunto de caracteres de ejecución"). Esto es para que pueda, al menos en principio, tomar un programa cuya fuente codificada en texto ASCII y ejecutarlo sin modificar en una computadora que use EBCDIC, solo compilándolo de forma adecuada; no tienes que convertir el texto fuente a EBCDIC primero.
Ahora, el compilador debe entender ambos conjuntos de caracteres si son diferentes, pero históricamente, el preprocesador de C ( fases de traducción 1 a 4) y el "compilador propiamente dicho" (fases 5 a 7) fueron dos programas separados y expresiones #if
es el único lugar donde el preprocesador debería conocer el conjunto de caracteres de ejecución. Por lo tanto, al definir su implementación como si el "conjunto de caracteres de ejecución" utilizado por el preprocesador coincide con el utilizado por el compilador, el estándar autoriza al preprocesador a hacer todo su trabajo en el conjunto de caracteres de origen , haciendo que la vida sea un poco más fácil. en 1989.
Habiendo dicho todo eso, me sorprendería mucho encontrar un compilador moderno que no haya hecho que ambas expresiones se evalúen con el mismo valor, incluso cuando la ejecución y los juegos de caracteres de origen son totalmente incompatibles. Los compiladores modernos tienden a tener preprocesadores integrados : las fases 1 a 7 se llevan a cabo con el mismo programa, e incluso si no lo hacen, la carga de ingeniería de especializar al preprocesador para que coincida con su conjunto de caracteres de ejecución con el compilador propiamente dicho es trivial hoy en día.
Para ampliar las otras respuestas correctas, un ejemplo real de un compilador C que no es ASCII que todavía se está utilizando es www-304.ibm.com/servers/resourcelink/svc00100.nsf/pages/… . De forma predeterminada, se supone que los archivos de origen están en la página de códigos 1047 de IBM (la versión de EBCDIC con el mismo repertorio que Latin-1). Sin embargo, tiene varias opciones de compilación diferentes para admitir no solo ASCII, sino también "código híbrido" o archivos de origen que contienen datos en más de una codificación. (Estos programas existen porque los compiladores MVS requieren que las declaraciones de sintaxis estén en la codificación IBM-1047 solamente).
A partir de la documentación, parece que sería posible #pragma CONVLIT(suspend)
con comandos como #pragma CONVLIT(suspend)
de una manera que realmente haría que esas dos declaraciones se evalúen de manera diferente en ese compilador. No tengo una copia para probar un MCVE.
Porque no todas las computadoras usan ascii o unicode.
En el pasado, un estándar llamado ebcdic era común. En ebcdic 500 el valor de ''z''
es 169 y el valor de ''a''
es 130. La expresión ''z''-''a''
evaluaría entonces a 39.
Esto explica por qué no puede asumir un cierto valor para una expresión del tipo ''a''
o incluso ''z''-''a''
. Sin embargo, no explica por qué no se garantiza que las dos expresiones en la Q sean iguales.
El preprocesador y el compilador son dos cosas diferentes. El preprocesador se ocupa de la codificación utilizada en el código fuente, mientras que el compilador apunta a la máquina para la que está compilando. Vea la respuesta de zwol para una explicación más elaborada.