2009-11-11 21 views
8

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.

+5

Busque un programa llamado "cdecl". Descargalo. Pega la declaración en ella. Se iluminado. –

+0

@Paul: ¡Lo intentaré y espero que no mate mi máquina! –

+1

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. –

Respuesta

21

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."

+3

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. –

+0

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. –

+3

-1 (en realidad no): toma argumentos no especificados en C – pmg

9

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.

+0

¿Cómo puede lanzar una matriz a un puntero de función? ¿Hay algún artículo que lo explique? –

+0

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

+0

Puedes hacer esto porque es C: puedes hacer lo que quieras. Es una idea terrible, pero puedes hacerlo. – Clyde

1

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.

2

Echa buf en un puntero de función, que toma argumentos no especificados y lo llama.

+1

-1 (no realmente): toma argumentos no especificados en C – pmg

+0

@pmg, gracias. Edité por respuesta. –

4

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).

+0

-1 (en realidad no): toma argumentos no especificados en C – pmg

+0

@pmg, buen punto. –

0

llama a un puntero a la función. la función no tiene argumentos.

Function Pointer - Wikipedia

+1

-1 (no realmente): la función tiene argumentos no especificados en C – pmg

+0

La función tiene (se proporciona) sin argumentos. El tipo de función tiene parámetros no especificados. –

+0

De acuerdo, dadas las otras respuestas, dejaré la publicación tal como está. – segy

2
 
((void(*)())buf)(); 
\------------/   cast `buf` to 
\---------/   type: pointer to function accepting a fixed but 
           unspecified number of arguments and 
           returning void 
\----------------/  and call that "function" 
+0

+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

5

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":/

Cuestiones relacionadas