¿Qué hace la expresión C((void(*)(void)) 0)(); ¿media?
(5)
((void(*)(void))0)();
Así que tenemos un tipo 0 entero que convierte a este tipo complicado (void(*))(void)
y luego lo ejecutamos. Source afirma que esto debería funcionar, pero ¿qué es lo que realmente funciona?
Este debe ser uno de esos chistes de C como #define TRUE FALSE
, supongo.
En algún sistema integrado (AVR microcontrolador, por ejemplo), esta podría ser una manera de implementar un salto (una llamada, realmente) al vector de reinicio.
Podría reiniciar el SW de esta manera, especialmente si ha deshabilitado las interrupciones antes de esto.
Esta es una función que no espera argumentos y no devuelve ningún valor:
void f(void)
Este es un puntero a una función que no espera argumentos y no devuelve ningún valor:
void (*p)(void)
Este es el tipo de ese puntero:
void (*)(void) /* just remove the p! */
Este es ese tipo entre paréntesis:
(void (*)(void))
Esta es una conversión a ese tipo (el tipo entre paréntesis, seguido de un valor):
(void (*)(void))0
¿Aún conmigo? hasta ahora tenemos el valor entero 0 convertido en un puntero a la función que no toma argumentos y devuelve nada.
El cast es una expresión con tipo puntero a función. Cuando tienes uno de esos, puedes llamarlo así:
(your expression here)(arguments to the function)
El primer conjunto de paréntesis es solo por precedencia, y algunas veces puede que no sea necesario (pero esta vez sí lo son). El final resulto:
((void (*)(void))0)(/* no args */);
Toma el valor 0, lo convierte en puntero a función esperando-no-argumentos-y-no devuelve nada, y lo llama, no proporciona argumentos.
Esto trata a NULL
como un puntero de función y lo ejecuta, debería elevar un sigbus o similar en la mayoría de los sistemas.
void(*)(void) <- type, function pointer taking no arguments and returning no value
(void(*)(void)) <- cast to above type
((...)0) <- cast NULL/0 to said type
((...)0)() <- execute the cast value as a function
La sintaxis para convertir la dirección en un puntero de función y luego llamarlo se vería así:
((void (*)(void))address)();
Aunque podría ser más claro hacer algo como esto:
void (*fptr)(void) = (void (*)(void))address;
fptr();
Dijo que ((void(*)(void))0)();
La instrucción se utiliza para saltar a 0 en firmwares por lo general. Es un poco impropio porque en realidad llama en 0 en lugar de saltar a 0, pero prácticamente no hace ninguna diferencia (se realizará un reinicio en caliente).
Los AVR normalmente cargarán el programa de aplicación del usuario en la dirección 0. Un programa de cargador de arranque que se carga en una dirección mucho más alta, puede saltar a (llamar a la función en) la dirección 0. Por lo tanto, la conversión y la llamada a la dirección 0 son útiles. construir en este entorno.