2011-11-05 12 views
25

Creo que no se puede invocar una función estática en un archivo fuente directamente desde fuera del archivo. Sin embargo, si de alguna manera logro obtener un puntero a esta función en otro archivo, ¿puedo entonces llamar a esta función desde ese archivo? En caso afirmativo, ¿hay algún escenario en el que nos gustaría tomar esta ruta en comparación con simplemente hacer que la función no sea estática?¿Se puede llamar a una función estática a través de un puntero de función en C?

+1

Me pregunto cuál es el comportamiento si se mezcla esto con la palabra clave 'inline' y/o las directivas propietarias del compilador que siempre alinearían una función. – mpontillo

+0

@mpontillo Creo que incluso si la función está marcada como 'en línea' pero la dirección se toma en un puntero a función, el compilador generará el cuerpo en el binario, al tiempo que lo contextualizará en otras funciones en el mismo módulo. –

Respuesta

28

Sí, puede exportar funciones estáticas entregándoles punteros. Este es un medio común de implementar el Factory pattern en C, donde puede ocultar las implementaciones de un conjunto completo de funciones de los módulos que las usan, y tiene un FuncPtr_t GetFunction(enum whichFunctionIWant) que las distribuye a los consumidores. Así es como funcionan muchas implementaciones de dynamic linking.

3

Sí, una función no estática en su archivo puede devolver un puntero a una función estática a cualquier lugar que desee.

9

Sin embargo, si de alguna manera logro obtener un puntero a esta función en otro archivo, ¿puedo entonces llamar a esta función desde ese archivo?

Sí, es perfectamente posible. La función no es visible para el enlazador, pero está allí en el ejecutable. Siempre puede saltar a su dirección.

Aunque no estoy seguro de los escenarios. Tal vez quieras que los demás solo llamen a tu función después de llamaron a alguna otra función (no estática, por supuesto). Entonces los tiene y lo obtiene, y luego pueden llamarlo.

3

Sí, puedes. Si tiene que llamar a una función que espera un puntero a una función como devolución de llamada, puede usar estática para que el símbolo de la función no contamine el espacio de nombres global y no provoque conflictos entre los enlazadores. El ejemplo más usado es probablemente qsort:

struct Data { ... }; 

static int compareData(const void* a, const void* b) { /* cast to Data and compare */ } 

... 
qsort(array, count, sizeof(Data), &compareData); 
4

Como el otro mencionado, puede hacerlo. Un ejemplo de por qué es deseable es para algún tipo de "controlador". Puede devolver una estructura que contiene las funciones abrir, cerrar, leer y escribir sin tener que hacer que las funciones reales sean accesibles al público.

0

Sí se puede, siempre se puede probar por ti mismo y saber:

Archivo1.c

#include <stdio.h> 

void call_hello(void (*fptr)(void)); 

static void hello(void) { 
    puts("hello"); 
} 

int main(void) 
{ 
    void (*fptr)(void) = hello; 

    call_hello(fptr); 

    return 0; 
} 

Archivo2.c

void call_hello(void (*fptr)(void)) 
{ 
    fptr(); 
} 
+8

A menudo no es un buen enfoque en C. "Funciona" y "es seguro, funcionará en todas partes, y no se basa en un comportamiento indefinido" a menudo son cosas muy diferentes. –

2

A menudo es útil para definir una pequeña función estática como función de trabajo para otra. Mire la norma qsort para un ejemplo: espera una función de comparación, y muy a menudo es mejor hacer esa función de comparación estática (por ejemplo, porque no es útil en ninguna otra parte, y porque qsort quiere que tenga alguna firma poco bonita).

Cuestiones relacionadas