2011-11-05 14 views
25

Credo che una funzione statica in un file sorgente non possa essere chiamata direttamente dall'esterno del file. Tuttavia, se in qualche modo riesco a ottenere un puntatore a questa funzione in un altro file, posso chiamare questa funzione da quel file. Se sì, esiste uno scenario in cui vorremmo seguire questa strada rispetto al semplice fatto di rendere la funzione non statica?È possibile chiamare una funzione statica tramite un puntatore a funzione in C?

+1

Mi chiedo quale sia il comportamento se si mescola questo con la parola chiave 'inline' e/o le direttive del compilatore proprietario che integrerebbero sempre una funzione. – mpontillo

+0

@mpontillo Credo che anche se la funzione è contrassegnata come 'inline' ma l'indirizzo è preso in un puntatore di funzione, il compilatore genererebbe il corpo nel binario, mentre lo incorpora anche in altre funzioni nello stesso modulo. –

risposta

28

Sì, è possibile esportare le funzioni statiche assegnando loro dei puntatori. Questo è un mezzo comune per implementare lo Factory pattern in C, in cui è possibile nascondere le implementazioni di un sacco di funzioni dai moduli che le utilizzano e disporre di un FuncPtr_t GetFunction(enum whichFunctionIWant) che li distribuisce ai consumatori. Ecco come funzionano molte implementazioni dynamic linking.

3

Sì, una funzione non statica nel file può restituire un puntatore a una funzione statica in qualsiasi punto.

9

Tuttavia, se in qualche modo riesco a ottenere un puntatore a questa funzione nel file , posso chiamare questa funzione da quel file.

Sì, è perfettamente possibile. La funzione non è visibile al linker, ma è lì nell'eseguibile. Puoi sempre saltare al suo indirizzo.

Non sono sicuro degli scenari. Forse vuoi che gli altri chiamino la tua funzione solo dopo il. Hanno chiamato qualche altra funzione (non statica, ovviamente). Quindi li hai e ottieni e poi possono chiamarlo.

3

Sì, è possibile. Se è necessario chiamare una funzione che si aspetta un puntatore a una funzione come callback, è possibile utilizzare la statica in modo che il simbolo della funzione non inquini lo spazio dei nomi globale e non causi conflitti di linker. L'esempio più utilizzato è probabilmente qsort:

struct Data { ... }; 

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

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

Come l'altro citato, puoi farlo. Un esempio del perché si potrebbe desiderare è una sorta di "driver". Potresti passare una struttura contenente le funzioni di apertura, chiusura, lettura e scrittura senza dover rendere pubblicamente accessibili le vere funzioni.

0

Sì, è possibile, si può sempre provare per voi stessi e scoprire:

file1.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; 
} 

file2.c

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

Spesso non è un buon approccio in C. "Funziona" e "è sicuro, funzionerà ovunque e non si basa su comportamenti indefiniti" sono spesso cose molto diverse. –

2

E 'spesso utile per definire una piccola funzione statica come funzione di lavoro per qualcun altro. Guarda lo standard qsort per un esempio: si aspetta una funzione di confronto, e molto spesso è meglio rendere statica la funzione di confronto (ad esempio perché non è utile altrove, e perché qsort vuole che abbia una firma un po 'sfavorevole).

Problemi correlati