Estoy leyendo un código de emulador y he respondido a algo realmente extraño:
switch (reg){
case 'eax':
/* and so on*/
}
¿Cómo es esto posible? Pensé que solo podrías switch
en tipos integrales. ¿Hay algún truco macro?
c
switch-statement
label
constants
Ian Colton
fuente
fuente
'eax'
y enumera el valor entero constanteint
, por lo que es legal. Sin embargo, el valor de una constante de varios caracteres está definido por la implementación, por lo que es posible que el código no funcione como se esperaba en otro compilador. Por ejemplo,eax
podría ser0x65
,0x656178
,0x65617800
,0x786165
,0x6165
, o alguna otra cosa.'eax' != 'ebx'
, por supuesto, solo falle uno o dos de sus ejemplos. Aunque puede haber algún código en algún lugar que de hecho asume*(int*)("eax") == 'eax'
y, por lo tanto, falla en la mayoría de sus ejemplos.'eax'
podría comparar igual ao'ebx'
a'ax'
, y la instrucción de cambio no funcionaría como se esperaba.Respuestas:
(Solo usted puede responder a la parte del "truco de macros", a menos que pegue más código. Pero aquí no hay mucho en lo que puedan trabajar las macros, formalmente no se le permite redefinir palabras clave ; el comportamiento al hacerlo no está definido).
Para lograr la legibilidad del programa, el desarrollador ingenioso está explotando el comportamiento definido por la implementación . no
'eax'
es una cadena, sino una constante de varios caracteres . Tenga en cuenta con mucho cuidado los caracteres de comillas simples alrededor . Lo más probable es que en tu caso te esté dando una que sea exclusiva de esa combinación de caracteres. (Muy a menudo, cada carácter ocupa 8 bits en 32 bits ). ¡Y todo el mundo sabe que puedes hacerlo !eax
int
int
switch
int
Finalmente, una referencia estándar:
El estándar C99 dice:
fuente
'ab'
from'a'
y'b'
.De acuerdo con el estándar C (6.8.4.2 La declaración de cambio)
y (6.6 Expresiones constantes)
Ahora, ¿qué es
'eax'
?El estándar C (6.4.4.4 Constantes de caracteres)
Entonces
'eax'
es una constante de carácter entero de acuerdo con el párrafo 10 de la misma secciónEntonces, 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 carácter (entre comillas simples) tiene 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.fuente
Como han dicho otros, esta es una
int
constante y su valor real está definido por la implementación.Supongo que el resto del código se parece a
Puede estar seguro de que 'eax' en la primera parte tiene el mismo valor que 'eax' en la segunda parte, así que todo funciona, ¿verdad? ... incorrecto.
En un comentario, @Davislor enumera algunos valores posibles para 'eax':
¿Observa el primer valor potencial? Es decir
'e'
, ignorando a los otros dos personajes. El problema es, probablemente, el programa utiliza'eax'
,'ebx'
y así sucesivamente. Si todas estas constantes tienen el mismo valor que el'e'
que terminas conEsto no se ve muy bien, ¿verdad?
Lo bueno de "definido por 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.
La parte mala es que algún otro pobre puede tomar el código e intentar compilarlo usando algún 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 le dará al menos un nombre de archivo exacto y un número de línea para el problema. Aún así, no tendrá un programa que funcione.
fuente
assert('eax' != 'ebx'); //if this fails you can't compile the code because...
¿hay algo que el autor original pudiera hacer para evitar otras fallas del compilador sin reemplazar la construcción por completo?>El fragmento de código utiliza una rareza histórica llamada constante de caracteres de varios caracteres , también conocida como varios caracteres .
'eax'
es una constante entera cuyo valor está definido por la implementación.Aquí hay una página interesante sobre varios caracteres y cómo se pueden usar, pero no deben:
http://www.zipcon.net/~swhite/docs/computers/languages/c_multi-char_const.html
Mirando hacia atrás en el espejo retrovisor, así es como el manual C original de Dennis Ritchie de los buenos viejos tiempos ( https://www.bell-labs.com/usr/dmr/www/cman.pdf ) especificaba las constantes de caracteres .
La última frase es todo lo que necesita recordar acerca de esta curiosa construcción: las constantes de carácter con más de un carácter son inherentemente dependientes de la máquina y deben evitarse.
fuente