Risposte:
inline
indica al compilatore di tentare di incorporare il contenuto della funzione nel codice chiamante invece di eseguire una chiamata effettiva.
Per piccole funzioni chiamate frequentemente che possono fare una grande differenza di prestazioni.
Tuttavia, questo è solo un "suggerimento" e il compilatore potrebbe ignorarlo e la maggior parte dei compilatori tenterà di "inline" anche quando la parola chiave non viene utilizzata, come parte delle ottimizzazioni, ove possibile.
per esempio:
static int Inc(int i) {return i+1};
.... // some code
int i;
.... // some more code
for (i=0; i<999999; i = Inc(i)) {/*do something here*/};
Questo ciclo stretto eseguirà una chiamata di funzione a ogni iterazione e il contenuto della funzione è in realtà notevolmente inferiore al codice che il compilatore deve inserire per eseguire la chiamata. inline
essenzialmente istruirà il compilatore a convertire il codice sopra in un equivalente di:
int i;
....
for (i=0; i<999999; i = i+1) { /* do something here */};
Saltare la chiamata alla funzione effettiva e tornare indietro
Ovviamente questo è un esempio per mostrare il punto, non un vero pezzo di codice.
static
si riferisce all'ambito. In C significa che la funzione / variabile può essere utilizzata solo all'interno della stessa unità di traduzione.
static
(con o senza inline
) può essere perfettamente nell'intestazione, non vedo motivo per cui no. I modelli sono per C ++, questa domanda riguarda C.
inline
è un buon stile, imo
inline
non indica al compilatore di eseguire alcun tentativo di inlining. Consente semplicemente al programmatore di includere il corpo della funzione in più unità di traduzione senza violazione ODR. Un effetto collaterale di ciò è che rende possibile al compilatore, quando vorrebbe inline la funzione, di farlo effettivamente.
Per impostazione predefinita, una definizione inline è valida solo nell'unità di traduzione corrente.
Se la classe di archiviazione è extern
, l'identificatore ha un collegamento esterno e la definizione inline fornisce anche la definizione esterna.
Se la classe di archiviazione è static
, l'identificatore ha un collegamento interno e la definizione inline è invisibile in altre unità di traduzione.
Se la classe di archiviazione non è specificata, la definizione inline è visibile solo nell'unità di traduzione corrente, ma l'identificatore ha ancora un collegamento esterno e deve essere fornita una definizione esterna in un'unità di traduzione diversa. Il compilatore è libero di utilizzare la definizione inline o esterna se la funzione viene chiamata all'interno dell'unità di traduzione corrente.
Poiché il compilatore è libero di incorporare (e non inline) qualsiasi funzione la cui definizione è visibile nell'unità di traduzione corrente (e, grazie alle ottimizzazioni del tempo di collegamento, anche in unità di traduzione diverse, sebbene lo standard C non tenga realmente conto che), per la maggior parte degli scopi pratici, non c'è differenza tra le definizioni di funzione static
e static inline
.
Lo inline
specificatore (come la register
classe di archiviazione) è solo un suggerimento per il compilatore e il compilatore è libero di ignorarlo completamente. I compilatori non ottimizzanti conformi agli standard devono solo onorare i loro effetti collaterali, e i compilatori ottimizzati eseguiranno queste ottimizzazioni con o senza suggerimenti espliciti.
inline
e register
non sono inutili, tuttavia, poiché istruiscono il compilatore a generare errori quando il programmatore scrive codice che renderebbe impossibili le ottimizzazioni: una inline
definizione esterna non può fare riferimento a identificatori con collegamento interno (poiché questi non sarebbero disponibili in un'unità di traduzione diversa) oppure definire variabili locali modificabili con durata di memorizzazione statica (poiché queste non condividono lo stato tra le unità di traduzione) e non è possibile prendere indirizzi di register
variabili -qualificate.
Personalmente, utilizzo la convenzione per contrassegnare le static
definizioni di funzione anche all'interno delle intestazioni inline
, poiché il motivo principale per inserire le definizioni di funzione nei file di intestazione è renderle inlinabili.
In generale, uso solo definizioni di static inline
funzioni e static const
oggetti oltre alle extern
dichiarazioni all'interno delle intestazioni.
Non ho mai scritto una inline
funzione con una classe di archiviazione diversa da static
.
inline
come se fosse effettivamente applicata all'inlining è fuorviante e probabilmente non corretta. Nessun compilatore moderno lo usa come suggerimento per inline o richiederlo per abilitare l'inlining di una funzione.
static
e static inline
. Entrambi rendono la definizione invisibile alle altre unità di traduzione. Quindi quale sarebbe una ragione ragionevole per scrivere static inline
invece di static
?
Dalla mia esperienza con GCC lo so static
e static inline
differisce in un modo in cui il compilatore emette avvisi sulle funzioni inutilizzate. Più precisamente quando dichiari la static
funzione e non è utilizzata nell'unità di traduzione corrente, il compilatore produce un avviso sulla funzione inutilizzata, ma puoi inibire quell'avvertimento cambiandolo in static inline
.
Quindi tendo a pensare che static
dovrebbe essere usato nelle unità di traduzione e trarre vantaggio dal controllo extra del compilatore per trovare le funzioni inutilizzate. E static inline
dovrebbe essere utilizzato nei file di intestazione per fornire funzioni che possono essere allineate (a causa dell'assenza di collegamenti esterni) senza emettere avvisi.
Purtroppo non riesco a trovare alcuna prova per questa logica. Anche dalla documentazione di GCC non sono riuscito a concludere che inline
inibisca gli avvisi di funzione inutilizzati. Apprezzerei se qualcuno condividesse i link alla descrizione di questo.
warning: unused function 'function' [clang-diagnostic-unused-function]
una static inline
funzione durante la clang-tidy
compilazione con (v8.0.1), che viene utilizzata in un'altra unità di traduzione. Ma sicuramente, questa è una delle migliori spiegazioni e ragioni per combinare static
& inline
!
In C, static
significa che la funzione o la variabile che definisci può essere usata solo in questo file (cioè l'unità di compilazione)
Quindi, static inline
indica la funzione inline che può essere utilizzata solo in questo file.
MODIFICARE:
L'unità di compilazione dovrebbe essere The Translation Unit
the compile unit
sia qualcosa che ho scritto per errore, non esiste una cosa del genere, la terminologia effettiva ètranslation unit
Una differenza non è a livello di linguaggio, ma a livello di implementazione popolare: alcune versioni di gcc rimuoveranno le static inline
funzioni non referenziate dall'output per impostazione predefinita, ma manterranno le static
funzioni semplici anche se non referenziate. Non sono sicuro a quali versioni si applichi, ma da un punto di vista pratico significa che potrebbe essere una buona idea usare sempre inline
per le static
funzioni nelle intestazioni.
inline
nella definizione? Implica anche di non usarlo per le extern
funzioni?
attribute((used))
e il suo utilizzo per consentire ad asm di fare riferimento a static
funzioni e dati altrimenti non referenziati .
static
riferisce all'ambito. In C significa che la funzione / variabile può essere utilizzata solo all'interno della stessa unità di traduzione.