C LanguageClassi di archiviazione


introduzione

Una classe di archiviazione viene utilizzata per impostare l'ambito di una variabile o funzione. Conoscendo la classe di archiviazione di una variabile, possiamo determinare il tempo di vita di tale variabile durante il tempo di esecuzione del programma.

Sintassi

  • [auto | register | static | extern] <Tipo di dati> <Nome variabile> [= <Valore>];

  • [static _Thread_local | extern _Thread_local | _Thread_local] <Tipo di dati> <Nome variabile> [= <Valore>]; / * poiché> = C11 * /

  • Esempi:

  • typedef int foo ;

  • extern int foo [2];

Osservazioni

Gli identificatori di classe di archiviazione sono le parole chiave che possono essere visualizzate accanto al tipo di livello superiore di una dichiarazione. L'utilizzo di queste parole chiave influisce sulla durata e sul collegamento all'archiviazione dell'oggetto dichiarato, a seconda che sia dichiarato nell'ambito di un file o nell'ambito di un blocco:

Parola chiave Durata di archiviazione collegamento Osservazioni
static Statico Interno Imposta il collegamento interno per gli oggetti nell'ambito del file; imposta la durata di archiviazione statica per gli oggetti nell'ambito del blocco.
extern Statico Esterno Implicito e quindi ridondante per oggetti definiti nell'ambito del file che hanno anche un inizializzatore. Se utilizzato in una dichiarazione sullo scope del file senza un inizializzatore, suggerisce che la definizione deve essere trovata in un'altra unità di traduzione e verrà risolta al momento del collegamento.
auto Automatico non pertinente Implicito e quindi ridondante per oggetti dichiarati a scopo di blocco.
register Automatico non pertinente Rilevante solo per gli oggetti con durata di archiviazione automatica. Fornisce un suggerimento per cui la variabile deve essere memorizzata in un registro. Un vincolo imposto è che non è possibile utilizzare l'operatore unario & "indirizzo di" su tale oggetto e pertanto l'oggetto non può essere sottoposto a aliasing.
typedef non pertinente non pertinente Non è un identificatore di classe di archiviazione in pratica, ma funziona come uno da un punto di vista sintattico. L'unica differenza è che l'identificatore dichiarato è un tipo, piuttosto che un oggetto.
_Thread_local Filo Interno esterno Introdotto in C11, per rappresentare la durata della memorizzazione dei thread . Se utilizzato a livello di blocco, deve includere anche extern o static .

Ogni oggetto ha una durata di archiviazione associata (indipendentemente dall'ambito) e un collegamento (rilevante solo per le dichiarazioni nell'ambito del file), anche quando queste parole chiave vengono omesse.

L'ordine degli specificatori della classe di memoria rispetto agli identificatori di tipo di primo livello ( int , unsigned , short , ecc.) E qualificatori di tipo di primo livello ( const , volatile ) non viene applicato, quindi entrambe le dichiarazioni sono valide:

int static const unsigned a = 5; /* bad practice */
static const unsigned int b = 5; /* good practice */

Tuttavia, è considerata una buona pratica inserire prima gli identificatori della classe di memoria, quindi qualsiasi qualificatore di tipo, quindi lo specificatore di tipo ( void , char , int , signed long , unsigned long long , long double ...).

Non tutti gli specificatori di classe di archiviazione sono legali in un determinato ambito:

register int x; /* legal at block scope, illegal at file scope */
auto int y; /* same */

static int z; /* legal at both file and block scope */
extern int a; /* same */

extern int b = 5; /* legal and redundant at file scope, illegal at block scope */

/* legal because typedef is treated like a storage class specifier syntactically */
int typedef new_type_name;

Durata di archiviazione

La durata dell'archiviazione può essere statica o automatica. Per un oggetto dichiarato, viene determinato in base all'ambito e agli identificatori della classe di archiviazione.

Durata dell'archiviazione statica

Le variabili con durata dell'archiviazione statica vivono durante l'intera esecuzione del programma e possono essere dichiarate sia nell'ambito di file (con o senza static ) sia nell'ambito di un blocco (mettendo static esplicito). Solitamente vengono allocati e inizializzati dal sistema operativo all'avvio del programma e recuperati al termine del processo. In pratica, i formati eseguibili hanno sezioni dedicate per tali variabili ( data , bss e rodata ) e queste intere sezioni del file vengono mappate in memoria in determinati intervalli.

Durata della memorizzazione del thread

C11

Questa durata di archiviazione è stata introdotta in C11. Questo non era disponibile negli standard C precedenti. Alcuni compilatori forniscono un'estensione non standard con semantica simile. Ad esempio, gcc supporta l' __thread che può essere utilizzato negli standard C precedenti che non avevano _Thread_local .

Le variabili con durata di memorizzazione del thread possono essere dichiarate sia nell'ambito del file che nell'ambito del blocco. Se dichiarato a livello di blocco, deve anche utilizzare static extern memorizzazione static o extern . La sua vita è l'intera esecuzione del thread in cui è stato creato. Questo è l'unico identificatore di archiviazione che può apparire accanto a un altro identificatore di memorizzazione.

Durata archiviazione automatica

Le variabili con durata di memorizzazione automatica possono essere dichiarate solo a livello di blocco (direttamente all'interno di una funzione o all'interno di un blocco in quella funzione). Sono utilizzabili solo nel periodo tra l'entrata e l'uscita dalla funzione o dal blocco. Una volta che la variabile esce dall'ambito (o ritornando dalla funzione o abbandonando il blocco), la sua memoria viene automaticamente deallocata. Qualsiasi ulteriore riferimento alla stessa variabile dai puntatori non è valido e porta a un comportamento non definito.

Nelle implementazioni tipiche, le variabili automatiche si trovano a determinati offset nel frame dello stack di una funzione o nei registri.

Collegamento esterno e interno

Il collegamento è rilevante solo per gli oggetti (funzioni e variabili) dichiarati nell'ambito del file e influisce sulla loro visibilità su diverse unità di traduzione. Gli oggetti con collegamento esterno sono visibili in ogni altra unità di traduzione (a condizione che sia inclusa la dichiarazione appropriata). Gli oggetti con collegamento interno non sono esposti ad altre unità di traduzione e possono essere utilizzati solo nell'unità di traduzione dove sono definiti.

Classi di archiviazione Esempi correlati