tipos - leer cadena de caracteres en c
Este código fuente está cambiando una cadena en C. ¿Cómo lo hace? (4)
(Solo usted puede responder la parte del "truco macro", a menos que pegue más código. Pero no hay mucho aquí para que las macros trabajen, formalmente no se le permite redefinir palabras clave ; el comportamiento al hacerlo no está definido).
Para lograr la legibilidad del programa, el ingenioso desarrollador está explotando el
comportamiento definido de implementación
.
''eax''
no
es una cadena, sino una
constante de varios caracteres
.
Observe con mucho cuidado los caracteres de comillas simples alrededor de
eax
.
Lo más probable es que te dé un
int
en tu caso que sea único para esa combinación de personajes.
(Muy a menudo cada personaje ocupa 8 bits en un
int
32 bits).
¡Y todos saben que puedes
switch
un
int
!
Finalmente, una referencia estándar:
El estándar C99 dice:
6.4.4.4p10: "El valor de una constante de carácter entero que contiene más de un carácter (por ejemplo, ''ab''), o que contiene un carácter o secuencia de escape que no se asigna a un carácter de ejecución de un solo byte, está definido por la implementación. "
Estoy leyendo un código de emulador y he contrarrestado algo realmente extraño:
switch (reg){
case ''eax'':
/* and so on*/
}
¿Cómo es esto posible?
Pensé que solo podías
switch
tipos integrales.
¿Hay algún truco macro pasando?
Como han dicho otros, esta es una constante
int
y su valor real está definido por la implementación.
Supongo que el resto del código se parece a
if (SOMETHING)
reg=''eax'';
...
switch (reg){
case ''eax'':
/* and so on*/
}
Puede estar seguro de que ''eax'' en la primera parte tiene el mismo valor que ''eax'' en la segunda parte, por lo que todo funciona, ¿verdad? ... incorrecto.
En un comentario, @Davislor enumera algunos valores posibles para ''eax'':
...
0x65
,0x656178
,0x65617800
,0x786165
,0x6165
u otra cosa
Observe el primer valor potencial?
Eso es solo
''e''
, ignorando los otros dos caracteres.
El problema es que el programa probablemente usa
''eax''
,
''ebx''
, etc.
Si todas estas constantes tienen el mismo valor que
''e''
terminas con
switch (reg){
case ''e'':
...
case ''e'':
...
...
}
Esto no se ve muy bien, ¿verdad?
Lo bueno de "definido por la implementación" es que el programador puede verificar la documentación de su compilador y ver si hace algo sensato con estas constantes. Si es así, casa gratis.
Lo malo es que algún otro tipo pobre puede tomar el código e intentar compilarlo usando otro compilador. Error de compilación instantánea. El programa no es portátil.
Como @zwol señaló en los comentarios, la situación no es tan mala como pensaba, en el mal caso, el código no se compila. Esto al menos le dará un nombre de archivo exacto y un número de línea para el problema. Aún así, no tendrá un programa de trabajo.
De acuerdo con el Estándar C (6.8.4.2 La declaración de cambio)
3 La expresión de cada etiqueta de caso será una expresión constante entera ...
y (6.6 Expresiones constantes)
6 Una expresión constante entera tendrá un tipo entero y solo tendrá operandos que sean constantes enteras, constantes de enumeración, constantes de caracteres , tamaño de expresiones cuyos resultados son constantes enteras y constantes flotantes que son operandos inmediatos de conversiones. Los operadores de conversión en una expresión constante entera solo convertirán tipos aritméticos en tipos enteros, excepto como parte de un operando al operador sizeof.
Ahora, ¿qué es
''eax''
?
El estándar C (6.4.4.4 constantes de caracteres)
2 Una constante de caracteres enteros es una secuencia de uno o más caracteres multibyte encerrados entre comillas simples , como en ''x'' ...
Entonces
''eax''
es una constante de caracteres enteros de acuerdo con el párrafo 10 de la misma sección
- ... El valor de una constante de carácter entero que contiene más de un carácter (por ejemplo, ''ab''), o que contiene un carácter o secuencia de escape que no se asigna a un carácter de ejecución de un solo byte, está definido por la implementación.
Entonces, de acuerdo con la primera cita mencionada, puede ser un operando de una expresión constante entera que se puede usar como etiqueta de caso.
Preste atención a que una constante de caracteres (encerrada entre comillas simples) tiene el tipo
int
y no es lo mismo que un literal de cadena (una secuencia de caracteres entre comillas dobles) que tiene un tipo de matriz de caracteres.
El fragmento de código utiliza una rareza histórica llamada constante de caracteres de varios caracteres , también conocida como caracteres múltiples .
''eax''
es una constante entera cuyo valor es la implementación definida.
Aquí hay una página interesante sobre múltiples caracteres y cómo se pueden usar, pero no deberían:
http://www.zipcon.net/~swhite/docs/computers/languages/c_multi-char_const.html
Mirando más atrás en el espejo retrovisor, así es como el manual C original de Dennis Ritchie de los viejos tiempos ( https://www.bell-labs.com/usr/dmr/www/cman.pdf ) especificaba constantes de caracteres .
2.3.2 Constantes de caracteres
Una constante de caracteres es 1 o 2 caracteres entre comillas simples ''''
''
'' ''. Dentro de una constante de caracteres, una comilla simple debe ir precedida de una barra diagonal inversa ''''/
''''. Ciertos caracteres no gráficos, y ''''/
'''' en sí, se pueden escapar de acuerdo con la siguiente tabla:
BS /b NL /n CR /r HT /t ddd /ddd / //
El escape ''''
/ddd
'''' consiste en la barra invertida seguida de 1, 2 o 3 dígitos octales que se toman para especificar el valor del carácter deseado. Un caso especial de esta construcción es ''''/0
'''' (no seguido de un dígito) que indica un carácter nulo.Las constantes de caracteres se comportan exactamente como enteros (no, en particular, como objetos de tipo de carácter). De conformidad con la estructura de direccionamiento del PDP-11, una constante de caracteres de longitud 1 tiene el código para el carácter dado en el byte de orden inferior y 0 en el byte de orden superior; una constante de carácter de longitud 2 tiene el código para el primer carácter en el byte bajo y el del segundo carácter en el byte de orden superior. Las constantes de caracteres con más de un carácter dependen inherentemente de la máquina y deben evitarse.
La última frase es todo lo que necesita recordar sobre esta curiosa construcción: las constantes de caracteres con más de un carácter dependen inherentemente de la máquina y deben evitarse.