2010-02-02 11 views
13

Existe la posibilidad de que la función estática se pueda evaluar fuera del alcance del archivo. ?Acceso a la función estática en otros archivos

+7

Si coloca la función en el archivo de encabezado. Luego habrá una versión estática en cada unidad de compilación. –

Respuesta

19

Depende de lo que quiere decir con "acceso". Por supuesto, la función no puede llamarse por nombre en ningún otro archivo, ya que es static en un archivo diferente, pero tiene un puntero a la función.

$ cat f1.c 
/* static */ 
static int number(void) 
{ 
    return 42; 
} 

/* "global" pointer */ 
int (*pf)(void); 

void initialize(void) 
{ 
    pf = number; 
} 
$ cat f2.c 
#include <stdio.h> 

extern int (*pf)(void); 
extern void initialize(void); 

int main(void) 
{ 
    initialize(); 
    printf("%d\n", pf()); 
    return 0; 
} 
$ gcc -ansi -pedantic -W -Wall f1.c f2.c 
$ ./a.out 
42 
12

No, a menos que haya un error en el compilador. Normalmente, el código de función estática no está etiquetado con un nombre utilizado para exportar la función en el archivo de objeto, por lo que no se presenta al vinculador y simplemente no se puede vincular a él.

Por supuesto, esto solo se aplica a llamar a la función por su nombre. Otro código dentro del mismo archivo puede obtener la dirección de la función y pasarla a una función no estática en otro archivo y luego la función de otro archivo puede llamar a su función estática.

4

Siguiendo el estándar, no se puede acceder a una función estática fuera del alcance del archivo por el nombre porque está sujeto a un enlace interno. Su nombre no se exporta ni se proporciona al vinculador. Sin embargo, todavía puede ser accedido y llamado por el puntero de función, como cualquier otra función.

16

Se podría invocar desde fuera del alcance mediante el puntero de función.

Por ejemplo, si usted tenía:

static int transform(int x) 
{ 
    return x * 2; 
} 

typedef int (*FUNC_PTR)(int); 

FUNC_PTR get_pointer(void) 
{ 
    return transform; 
} 

entonces una función fuera del alcance puede llamar get_pointer() y utilizar el puntero de función vuelto a llamar a transformar.

+1

Creo que debería ser "int (* get_pointer (int)) (void)". – paxdiablo

+0

@paxdiablo y @caf - gracias. –

1

No, el objetivo de la palabra clave static es limitar el alcance del nombre de la función al archivo.

6

No se puede acceder fuera de un archivo por su nombre. Pero también puedes asignarlo al puntero de función y usarlo donde quieras.

3

Solo con engaño. La función generalmente no es visible para el enlazador, por lo que no le permitirá hacerlo.

Pero, si se proporciona una función dentro de la misma unidad de compilación (como la función estática), que devuelve la dirección de esa función:

En main.c:

#inclde <stdio.h> 
int (*getGet7(void))(void); 
int main (void) { 
     int (*fn)(void) = getGet7(); 
     printf ("Result is: %d\n", fn()); 
     return 0; 
} 

En hidden.c:

static int get7 (void) { 
     return 7; 
} 
int (*getGet7(void)) (void) { 
     return get7; 
} 

Esto dará como resultado que se llame a la función estática get7.

pax> gcc -o demo main.c hidden.c ; ./demo 
Result is: 7 
5

"Accessed"? Depende de lo que quieras decir con este término. Supongo que cuando dices "función estática" estás hablando de la función independiente declarada static (declarada con enlace interno) en oposición a las funciones de miembro de clase estáticas en C++, ya que estas últimas son obvias y de fácil acceso desde cualquier lugar.

Ahora, una función autónoma declarada static tiene un enlace interno. No puede ser vinculado a desde cualquier otra unidad de traducción.O, en otras palabras, no se puede hacer referencia al por el nombre desde cualquier otra unidad de traducción. Si eso es lo que quiso decir con "acceso desde fuera del alcance del archivo", entonces no, no se puede hacer.

Sin embargo, si las otras unidades de traducción de alguna manera obtienen un puntero a esa función (es decir, si de alguna manera permite que el puntero "se filtre" en el mundo exterior), cualquiera puede invocar esa función realizando una llamada "acceder a él. Por ejemplo, si se declara

static void foo_static(void) { 
} 

extern void (*foo_ptr)(void) = foo_static; 

entonces en cualquier otra unidad de traducción que el usuario será capaz de hacer

extern void (*foo_ptr)(void); 
foo_ptr(); 

y la llamada se vaya a su función foo_static. No sé si ese tipo de acceso califica como "acceso" en su pregunta.

Cuestiones relacionadas