¿Qué significa `((void(*)()) 0x1000)();` significa?
pointers (4)
La persona que escribió ese código debería haberlo reescrito de forma legible como:
#define ADDRESS_OF_FUNCTION_X 0x1000
typedef void (*func_ptr_t)(void);
...
func_ptr_t function_x = (func_ptr_t)ADDRESS_OF_FUNCTION_X;
function_x();
Lo que el código hace ahora está prácticamente auto-documentado.
Esta pregunta ya tiene una respuesta aquí:
Aquí hay un código que tiene el propósito de configurar el contador del programa para saltar a la dirección 0x1000
. Sé lo que hace, pero no entiendo cómo. Está relacionado con mi falta de conocimiento del lenguaje C. Tal vez podrias iluminarme. Aquí está la declaración / función (incluso no sé lo que es :))
((void (*)())0x1000)();
Creo que es un puntero a una función que devuelve void
y no acepta ningún argumento. Por favor, corríjame si estoy equivocado.
Una constante
0x1000
se lanza a un tipo:
(type)0x1000
El tipo es void (*)()
- un puntero (asterisco) para una función que no toma parámetros (paréntesis vacíos a la derecha) (oops, vea el comentario por pmg ) y no devuelve ningún valor ( void
a la izquierda). Paneles adicionales en el asterisco impiden asociarlo a void
, lo que crearía incorrectamente un tipo void *
aquí.
Entonces, después del lanzamiento, tienes un puntero a una función vacía sin parámetros en el 0x1000 de la dirección:
(void (*)())0x1000
Y esa función ...
((void (*)())0x1000)
se llama al agregar una lista de parámetros vacíos:
((void (*)())0x1000)();
(void (*)())
es un puntero a una función que devuelve void
y toma un número de argumentos no especificado, pero fijo.
(void (*)())0x1000
está lanzando el literal 0x1000
al tipo anterior.
Finalmente, el sufijo ()
llama a esa función. La expresión anterior debe estar entre paréntesis, de lo contrario, el sufijo ()
se vinculará al 0x1000
que no es sintácticamente válido.
Depende de ti comprobar si el lanzamiento es realmente válido. Si no, entonces el comportamiento de su programa no está definido .
C
declaraciones C
se decodifican desde adentro hacia afuera usando una regla simple: comience desde el identificador y verifique en el lado derecho para []
(matriz) o ()
(función) luego verifique en el lado izquierdo el tipo de los valores (almacenados en array o devuelto por la función), sin cruzar los paréntesis; escapar de los paréntesis y repetir.
Por ejemplo:
void (*p)()
p
es (nada a la derecha) un puntero (a la izquierda, no cruza los paréntesis) para (escapar de los paréntesis, leer el siguiente nivel) una función (derecha) que no devuelve nada (izquierda).
Cuando falta el identificador ( p
en este caso), todo lo que queda es una declaración de tipo.
Un tipo encerrado entre paréntesis, delante de un valor es un tipo de conversión.
(void (*)())0x1000
convierte el número 0x1000
en un puntero a una función que no devuelve nada (consulte lo que está fuera de los paréntesis en el párrafo sobre la declaración de p
anterior).
En el siguiente nivel, la expresión anterior (un puntero a una función se puede usar de la misma manera que un nombre de función) se usa para ejecutar el código apuntado a.
Vea a continuación la expresión completa descompuesta:
(
(
void (*)() /* type: pointer to function that doesn''t return anything */
)0x1000 /* value 0x1000 treated as a value of the type declared above */
) /* enclose in parentheses to specify the order of evaluation */
(); /* the pointer above used as a function name to run the code */