2013-04-26 14 views
24

ho definito la mia funzione in .c (senza dichiarazione di intestazione) come qui:C99 funzione inline nel file .c

inline int func(int i) { 
return i+1; 
} 

Poi nello stesso file sotto lo uso:

... 
i = func(i); 

E durante il collegamento ho ottenuto "riferimento non definito a 'func'". Perché?

+2

O renderlo 'static' o fornire una definizione non inline che il linker può trovare. –

+0

Vedere anche http://stackoverflow.com/questions/6312597 – Jens

risposta

32

Il modello inline in C99 è un po 'diverso rispetto alla maggior parte della gente pensa, e, in particolare, diverso da quello usato da C++

inline è solo un accenno in modo tale che il compilatore non si lamenta sui simboli doppiamente definite. Non garantisce che una funzione sia in linea, né che in realtà venga generato un simbolo, se necessario. Per forzare la generazione di un simbolo che ci si deve aggiungere una sorta di esemplificazione dopo la definizione inline:

int func(int i); 

Di solito si avrebbe la definizione inline in un file di intestazione, che viene poi incluso in più File .c (unità di compilazione). E avresti solo la linea sopra in esattamente una delle unità di compilazione. Probabilmente vedi solo il problema che hai perché non stai usando l'ottimizzazione per l'esecuzione del compilatore.

Quindi, il tuo caso d'uso di avere il inline nel file .c non ha molto senso, meglio usare solo static per quello, anche un ulteriore inline non ti compra molto.

+0

my bad, una dichiarazione di file-scope 'extern' senza' inline' * fa * obbliga la definizione a non essere in linea – Christoph

+2

Ho una domanda, perché questa situazione si verifica quando l'ottimizzazione è disattivata?Quando lo accendo con l'opzione gcc -O1 verrà semplicemente compilato, quale opzione nell'ottimizzazione di gcc fornisce questo codice per essere compilato nel modo corretto? – Lazureus

+1

@Lazureus, quando si compila con '-O0', suppongo che intendi ciò, di solito gcc non esegue alcuna funzione in linea. Quindi * devi * avere i simboli definiti da qualche parte, altrimenti non troverà alcuna delle funzioni 'inline' dichiarate-definite. –

21

La semantica in linea C99 viene spesso fraintesa. L'identificatore inline ha due scopi:

Innanzitutto, come suggerimento del compilatore in caso di dichiarazioni static inline e extern inline. La semantica rimane invariata se si rimuove lo specificatore.

secondo luogo, in caso di greggio inline (cioè senza static o extern) per fornire una definizione in linea come alternativa a uno esterno, che deve essere presente in un'unità diversa traduzione. Non fornire quello esterno è un comportamento non definito, che si manifesterà normalmente come errore di collegamento.

Ciò è particolarmente utile se si desidera inserire una funzione in una libreria condivisa, ma anche rendere disponibile per l'ottimizzazione il corpo della funzione (ad esempio, allineamento o specializzazione). Supponendo un compilatore sufficientemente intelligente, questo consente di recuperare molti dei vantaggi dei modelli C++ senza dover passare attraverso i telai del preprocessore.

Nota che è un po 'più disordinata di quanto ho descritto qui come avere un altro file di portata dichiarazione esterna non in linea attiverà il primo caso, come descritto nella risposta Jens', anche se la definizione stessa è inline invece di extern inline. Questo è in base alla progettazione in modo che sia possibile avere una singola definizione in linea in un file di intestazione, che è possibile includere nel file di origine che fornisce quello esterno aggiungendo una singola riga per la dichiarazione esterna.

+0

questa risposta è in qualche modo obsoleta - ho pensato che ci fosse un errore in quello di Jens, ma ho scoperto che mi sbagliavo ... – Christoph

+3

In realtà, spiegare quando è così utile semantico è una valida risposta (almeno per me). – Vorac

Problemi correlati