2014-12-18 8 views
5

Sto sviluppando in C da un po 'di tempo, provenendo da linguaggi orientati agli oggetti come C++ e Java, e mentre utilizzo le funzioni di libreria standard come fread() e strtok(), ho iniziato a chiedermi: come funzionano queste funzioni per la memorizzazione di variabili correlate al loro stato?In che modo le librerie C memorizzano le variabili di stato?

Ad esempio, si comporta in modo diverso per le chiamate successive e fread() tiene traccia della propria posizione nel file. Queste informazioni devono essere archiviate da qualche parte e in un linguaggio orientato agli oggetti esistono costrutti di ambito come private o protected per proteggere questi valori da modifiche indesiderate, ma per quanto ho capito C non li ha.

Quindi, come vengono memorizzati in modo sicuro? Oppure sono globali e modificabili da qualsiasi luogo? La domanda è nata quando stavo scrivendo un file di intestazione con funzioni di utilità che avevano bisogno di memorizzare informazioni di stato simili. Qual è il modo "giusto" per fare questo genere di cose in C, e come viene gestito nelle librerie esistenti?

+3

'fread' non ha bisogno di salvare lo stato tra le chiamate, visto che richiede una' struct file' che memorizza tutte le informazioni necessarie da 'fread'. –

risposta

7

Queste chiamate utilizzano le variabili static. Una variabile statica locale conserva il suo valore tra le chiamate di funzione. Una variabile statica globale o una funzione è accessibile solo da altre funzioni dichiarate nello stesso file.

+0

Proprio come una nota a margine, è ancora possibile raggiungere, ad esempio, una variabile globale statica (scope del file) da un altro file passando un puntatore (l'indirizzo) alla variabile. – Jite

+0

Lo _ nella stessa parte file_ era quello che mi mancava. Non mi rendevo conto che l'accesso alle variabili statiche globali era limitato da file. Grazie! – dasizeman

+1

@sizeman Si noti che, come ho cercato di spiegare sopra, è il * linker * che non può vederlo al di fuori del file, tuttavia se si ha un file 'A' con un' int stat' globale si può passare l'indirizzo di 'a' nel file' B' e continua ad accedere alla variabile dal file 'B'. Penso che sia importante saperlo, anche se non è qualcosa che fai ogni giorno. – Jite

8

Nel caso di fread() lo stato è memorizzato in una struttura FILE. La struttura è una risorsa allocata da fopen() che restituisce un puntatore ad esso, e si passa quel puntatore a ogni chiamata operazione file. La risorsa viene rilasciata quando viene chiamato fclose(). La risorsa FILE può essere allocata da un pool statico o può essere allocata dinamicamente dall'heap, che dipenderebbe dall'implementazione. Ad esempio:

RESOURCE* getResource() 
{ 
    return malloc(sizeof(RESOURCE)) ; 
} 

int useResource(RESOURCE* r) 
{ 
    return r.index++ ; 
} 

void releaseResource(RESOURCE* r) 
{ 
    free(r) ; 
} 

strtok() invece contiene un puntatore statico interno che viene inizializzato quando viene trasmesso e utilizzato come punto di partenza quando viene passato un puntatore nullo una stringa.

Ad esempio:

int getState() 
{ 
    static int state = 0 ; 
    return state++ ; 
} 

int main() 
{ 
    int s ; 

    do 
    { 
     s = getState() ; 
     printf("state = %d\n", s ; 

    } while(s < 10) ; 
} 
+0

Usando il tuo esempio per chiarire qualcosa, nel tuo secondo snippet di codice, non sono riuscito ad accedere a 'state' né a puntarlo direttamente da' main() 'corretto? – dasizeman

+1

@sizeman: corretto, la funzione getState dovrebbe restituire esplicitamente un puntatore come nell'esempio getResource, in modo che lo stato sia accessibile esternamente. Queste non sono le uniche possibilità, sono solo gli approcci usati da fread e strtok. Ad esempio, è possibile restituire un handle o un indice ai dati trattenuti internamente piuttosto che un puntatore o un tipo opaco. – Clifford

Problemi correlati