Estoy intentando averiguar qué hace el siguiente código en C?Explicación de colada complicada en C
((void(*)())buf)();
donde 'buf' es una matriz de char
.
Estoy intentando averiguar qué hace el siguiente código en C?Explicación de colada complicada en C
((void(*)())buf)();
donde 'buf' es una matriz de char
.
Vamos a dar un paso a la vez.
void(*)()
Este es un puntero a una función que toma argumentos no especificados y no tiene valor de retorno.
(void(*)())buf
simplemente coloca el buf en esta función tipo de puntero. Finalmente,
((void(*)())buf)();
llama a esta función.
Por lo tanto, toda la instrucción es "interpretar buf
como un puntero a una función void
sin argumentos, y llamar a esa función."
Convertir un búfer de caracteres en una función y llamarlo es malo. Es un intento de auto modificar código, o es un intento malicioso de hacer algún tipo de ataque. De cualquier manera, evítelo a toda costa. –
Corrígeme si me equivoco, pero ¿no es el valor del puntero (la dirección de la matriz) lo que se trata como una función, no el contenido de la matriz? "interpretar * el valor * en buf" suena un poco como si dijera que el contenido se interpreta como un puntero a una función. –
-1 (en realidad no): toma argumentos no especificados en C – pmg
Envía buf
a un puntero de función de tipo void(*)()
(Una función que no devuelve nada/vacío y toma argumentos no especificados) y lo llama.
El estándar ANSI no permite realmente el lanzamiento de punteros de datos normales para funcionar con punteros, pero su plataforma puede permitirlo.
¿Cómo puede lanzar una matriz a un puntero de función? ¿Hay algún artículo que lo explique? –
Un puntero es simplemente una colección de bytes como cualquier otro valor (que, por lo tanto, se puede presentar en C como una matriz de caracteres). Probablemente encontrará que en otro lugar del programa se realizó el reverso de esto: 'char * buf = (char *) function;' o algo similar. – Wernsey
Puedes hacer esto porque es C: puedes hacer lo que quieras. Es una idea terrible, pero puedes hacerlo. – Clyde
Supongo que en muchas circunstancias, bloquea la máquina. De lo contrario, trata la matriz como un puntero a una función que devuelve vacío y lo invoca.
Echa buf
en un puntero de función, que toma argumentos no especificados y lo llama.
-1 (no realmente): toma argumentos no especificados en C – pmg
@pmg, gracias. Edité por respuesta. –
Esto arroja buf
al tipo void (*)()
, un puntero a una función que toma los parámetros no especificados y no devuelve nada. Luego llama a la función en esa dirección (los dos paréntesis más a la derecha).
-1 (en realidad no): toma argumentos no especificados en C – pmg
@pmg, buen punto. –
llama a un puntero a la función. la función no tiene argumentos.
((void(*)())buf)(); \------------/ cast `buf` to \---------/ type: pointer to function accepting a fixed but unspecified number of arguments and returning void \----------------/ and call that "function"
+1 Tiene razón sobre el número de parámetros no especificado. Si hubieras aclarado con un ejemplo, probablemente habrías apreciado más tu comprensión :) – Andomar
Puede encontrar "programación de experto c" una buena lectura - desempaquetar este tipo de cosas está en uno de los capítulos, si mal no recuerdo. Ha pasado mucho tiempo desde que lo leí, pero recuerdo haber pensado que valía la pena el esfuerzo en ese momento. http://www.amazon.com/Expert-Programming-Peter-van-Linden/dp/0131774298
Tiendo a utilizar el comando "cdecl" cuando me encuentro con una declaración alucinante. Ejemplo:
[[email protected]]$ cdecl
Type `help' or `?' for help
cdecl> explain (void(*)())buf
cast buf into pointer to function returning void
Aunque hay casos en los que me hubiera gustado que hay una herramienta que hay que explica la salida de "cdecl":/
Existe una versión en línea de la herramienta 'cdecl' que LSC mencionó que puede ser útil: http://www.cdecl.org/
Busque un programa llamado "cdecl". Descargalo. Pega la declaración en ella. Se iluminado. –
@Paul: ¡Lo intentaré y espero que no mate mi máquina! –
Este código podría aparecer razonablemente en un JIT, o en el SO en un enlazador/cargador dinámico. Como otros han dicho, es aterrador, pero solo si lo has encontrado en una aplicación típica. En su lugar apropiado, no es algo aterrador, solo cosas difíciles. –