Non capisco però dove e come utilizzarla. Se la funzione che voglio
sviluppare inline
si chiama foo() e viene utilizzata solo in un modulo file.c, la cosa è
semplice:
--- file.c ---
#pragma inline foo
void foo(void)
{
...
}
...
foo();
...
---
Se, però, la funzione foo() viene usata in più moduli, per esempio
file1.c e file2.c,
ho messo sia la direttiva #pragma, sia la funzione foo() in un file .h
(file.h) che vado
ad includere sia in file1.c che in file2.c. Il linker, però, mi dà un
warning dicendo
che la definizione di un simbolo è duplicata.
Magari il tutto funziona, ma questi messaggi mi scocciano abbastanza.
Non c'è
modo di evitare questo warning? Qual è la tecnica giusta per
utilizzare le funzioni
inline?
Dovrebbe essere perch� in effetti viene inclusa due volte prova con le
condizioni del preprocessore, del tipo
#define _MIOFILE_H
e nei file.c una cosa del tipo
#ifndef _MIOFILE_H
#include "file.h"
#endif
> Magari il tutto funziona, ma questi messaggi mi scocciano abbastanza.
> Non c'�
> modo di evitare questo warning?
I warning vengono dati a ragione, se sai quel che fai e perch� lo fai
puoi ignorarli
Non risolverei. E' un warning del linker e non del compilatore perchè
si ritrova
con lo stesso simbolo definito due volte in due posti diversi.
Con il trucco delpreprocessore non potrei risolvere questo problema,
ma solo
la doppia inclusione durante la compilazione di un file, e non è
questo il
problema.
Ho provato a definire le funzioni inline anche static in modo da
rendere
privato nel modulo il simbolo. Funziona, nel senso che non ottengo più
quell'errore, ma mi danno warning i file che includono lo stesso
file.h per
altri motivi, ma non usano la funzione static inline. In questo caso è
il
compilatore che mi dà errore di simbolo statico definito ma non usato.
> > Magari il tutto funziona, ma questi messaggi mi scocciano abbastanza.
> > Non c'è
> > modo di evitare questo warning?
>
> I warning vengono dati a ragione, se sai quel che fai e perchè lo fai
> puoi ignorarli
Purtroppo non mi piace compilare e vedere warning da ignorare. Facendo
così
sono sicuro che un giorno non baderò ad un warning importante.
No.
allora:
1) leggere la doc del compilatore aiuta a capire come usare i #pragma
2) se proprio sei cosi pigro si dovrebbe usare cosi:
in file.c
#pragma inline
void foo(void)
{
//quello che e'
}
fine.
Ciao Jack
Già fatto e non m'è stato d'aiuto.
> 2) se proprio sei cosi pigro si dovrebbe usare cosi:
Grazie del pigro, ma penso di non esserlo stato... in questo caso
(normalmente lo sono :-)).
> in file.c
>
> #pragma inline
> void foo(void)
> {
> //quello che e'
>
> }
E se volessi usare foo() in file2.c, sviluppandola sempre inline?
la usi tranquillamente.
il #pragma dichiara che la funzione e' da essere usata come inline. Il
compilatore si arrangia a trovare i posti dove e' usata e a sostituire/
inserire il codice.
Ciao Jack
E come fa il compilatore ad inserire il codice della foo() in modo
inline
se non conosce il codice stesso in quanto è inserito in file.c e non
in file2.c
e neanche in file.h?
Facendo come dici tu, ottengo una normale chiamata a funzione.
Secondo me non c'è alternativa. Se vuoi una funzione inline DEVI avere
il codice nel file.c o in un suo file incluso, altrimenti il
compilatore non
potrebbe compilarla in modo inline.
a questo punto pare abbastanza chiaro che tu non hai idea di come
funzioni un compilatore/linker.
Studia.
Poi ne riparliamo.
Ciao Jack
Potrebbe anche essere, anzi sicuramente è così. Non mi sono mai
reputato un pozzo di scienza.
Ed è proprio per questo che ho provato a mettere la direttiva #pragma
inline
nel file .h, il codice della funzione nel file1.c e a richiamarla nel
file2.c.
Ottengo un eseguibile finale, però se vado a guardare nel listing, il
file2.c
richiama la foo() mediante un CALL e non in modo inline.
Se metto il codice nel .h (non cambio nulla nel file2.c),
effettivamente foo()
viene sviluppata inline ma il linker mi dà warning sul simbolo
duplicato.
> Potrebbe anche essere, anzi sicuramente è così. Non mi sono mai
> reputato un pozzo di scienza.
gia'.
> Ed è proprio per questo che ho provato a mettere la direttiva #pragma
> inline
> nel file .h, il codice della funzione nel file1.c e a richiamarla nel
> file2.c.
> Ottengo un eseguibile finale, però se vado a guardare nel listing, il
> file2.c
> richiama la foo() mediante un CALL e non in modo inline.
che non e' quello che ti ho detto di fare.
> Se metto il codice nel .h (non cambio nulla nel file2.c),
> effettivamente foo()
> viene sviluppata inline ma il linker mi dà warning sul simbolo
> duplicato.
si, ma non si mette il codice nel .h
se fai come ti ho detto funziona.
ma non ho intenzione di spiegarti perche', cosi come non ho intenzione
di spiegarti l'utilizzo dei .h in generale (che evidentemente non sai
come si usano, cosa servono e come il pre-processore li processa).
come detto: studia.
leggiti come funzionano i compilatori (in generale e in particolare
quello che stai usando ora): capirai perche' il #pragma inline va
messo davanti al codice della funzione che vuoi inline.
Ciao Jack
> Se metto il codice nel .h (non cambio nulla nel file2.c),
> effettivamente foo() viene sviluppata inline ma il linker mi dà
> warning sul simbolo duplicato.
Non ho mai usato la direttiva pragma ma solo la definizione della
funzione come:
void inline foo(void)
{
// corpo funzione
}
e nel .h la dichiarazione
extern void inline foo(void);
Da quanto ricordo ora ha sempre funzionato correttamente come funzione
inline senza generare warnings ne dalla compilazione ne dal linker.
Ciao
Giovanni
--
A computer is like an air conditioner,
it stops working when you open Windows.
< http://giovanni.homelinux.net/ >
Prima di tutto, bisogna dire che dichiarare una funzione inline e' solo un suggerimento al compilatore. Ogni compilatore puo' poi avere dei flag particolari per forzare l'espansione in linea, ma e' a discrezione del compilatore, non dello standard C.
C'e' poi un problema che riguarda in particolare l'implementazione di inline in C99, che e' diversa da come e' fatta per esempio in C++.
Non e' sbagliato dichiarare *e* definire una funzione inline nell'header file. Infatti e' la maniera in cui si fa pure in C++:
Se ho un due moduli (foo.c e bar.c) che chiamano una funzione inline chiamata myinlinefunc():
----
<foo.c>=
#include "myinlinefunc.h"
int
foo(void)
{
return myinlinefunc();
}
----
----
<bar.c>=
#include "myinlinefunc.h"
int
bar(void)
{
return myinlinefunc();
}
----
myinlinefunc.h puo' essere scritto cosi':
----
<myinlinefunc.h>=
static inline
int myinlinefunc()
{
return 1;
}
----
In questo caso, il compilatore trova la definizione/dichiarazione in ogni module, ma siccome la funzione e' dichiarata static, il suo simbolo non da conflitti nella fase di link.
E per esempio, in questo caso, gcc -O2 (ovvero con ottimizzazione) espande la funzione in linea.
In C++ per esempio, le funzioni membro inline di una classe devono essere dichiarate *e* definite all'interno dell'header file dove viene dichiarata la classe.
In C99, hanno permesso che la dichiarazione inline possa apparire con funzioni dichiarate 'extern', in modo tale da permettere non solo la definizione nel .h, ma anche in un modulo separato .c.
Se la funzione viene espansa inline, la funzione nel .h viene espanda in linea, altrimenti la funzione nel modulo .c viene usata.
Il problema in questo caso non e' il compilatore, ma il linker.
Siccome una funzione dichiarata extern ha visibilita' globale, il linker rileva un conflitto.
Questo e' un problema riportato per il linker ld della GNU.
Altri linker potrebbero non avere problemi, per esempio Mac OS X e Windows, in quanto hanno linker meno generici e ottimizzati per il loro compilatore.
Se tu dichiari una funzione inline nel .h, e la definisci in un suo modulo .c, la funzione non verra' mai espansa in linea, in quanto l'espansione non e' generata dal linker, ma dal compilatore, che compila solo un modulo alla volta, e deve avere la definizione disponibile, appunto dal file .h
In generale, per dichiarare un funzione inline, la si dichiara `static inline` e la si definisce nell'header file.
Lascia il resto come e' (usando pragma), ma dichiara la funzione `static`.
Prova e dimmi se funge.
Dovresti mettere la definizione in un .h diverso, e includere questo nuovo .h solo se la funzione e' necessaria a questo punto.
Magari il tuo compilatore ha un flag per disabilitare questo warning di funzione definita ma non usata, anche perche' io non l'ho mai visto.
Mamma mia, come sei acido... Non ho intenzione di continuare la mera
polemica con te. Se preferisci considerami stupido, pigro, ecc. ecc.
non mi interessa molto. Se ti va, continuiamo la discussione tecnica
altrimenti non intasiamo il gruppo con: studia, ma io ho studiato,
allora
sei pigro, non sono pigro...
> > Ed è proprio per questo che ho provato a mettere la direttiva #pragma
> > inline
> > nel file .h, il codice della funzione nel file1.c e a richiamarla nel
> > file2.c.
> > Ottengo un eseguibile finale, però se vado a guardare nel listing, il
> > file2.c
> > richiama la foo() mediante un CALL e non in modo inline.
>
> che non e' quello che ti ho detto di fare.
Tu mi hai detto solo questo:
> in file.c
>
> #pragma inline
> void foo(void)
> {
> //quello che e'
>
> }
Se faccio così la funzione foo() viene espansa inline nel file.obj.
Se devo usare la foo() in un altro file e la voglio sempre inline
come mi devo comportare secondo te? Io le ho provate tutte e
alla fine ottengo sempre un warning, oppure una espansione
non inline.
> > Se metto il codice nel .h (non cambio nulla nel file2.c),
> > effettivamente foo()
> > viene sviluppata inline ma il linker mi dà warning sul simbolo
> > duplicato.
>
> si, ma non si mette il codice nel .h
Detta così non mi sembra corretto. Il kernel di linux è pieno di
funzioni inline dichiarate e definite nei file .h.
> se fai come ti ho detto funziona.
> ma non ho intenzione di spiegarti perche', cosi come non ho intenzione
> di spiegarti l'utilizzo dei .h in generale (che evidentemente non sai
> come si usano, cosa servono e come il pre-processore li processa).
Capisco che tu sia offeso dal fatto che un codice di funzione possa
essere
messo in un file .h ed infatti è una cosa che non faccio mai.
Ma mi sembra di capire che le funzioni inline fanno eccezione, come
recita
anche il manuale di GCC:
--- from http://gcc.gnu.org/onlinedocs/gcc/Inline.html ---
This combination of inline and extern has almost the effect of a
macro.
The way to use it is to put a function definition in a header file
with these
keywords, and put another copy of the definition (lacking inline and
extern)
in a library file. The definition in the header file will cause most
calls to the
function to be inlined. If any uses of the function remain, they will
refer to
the single copy in the library.
---
> come detto: studia.
> leggiti come funzionano i compilatori (in generale e in particolare
> quello che stai usando ora): capirai perche' il #pragma inline va
> messo davanti al codice della funzione che vuoi inline.
Cosa che ho fatto nel file.c dove è definita la funzione inline. Il
problema
è negli altri file che usano quella funzione e devono usarla inline.
Purtroppo il mio compilatore non è nè C99 né GCC, quindi vuole per
forza
#pragma.
> Detta così non mi sembra corretto. Il kernel di linux è pieno di
> funzioni inline dichiarate e definite nei file .h.
io non prenderei il codice del kernel di linux come esempio su come
scrivere codice...
> Capisco che tu sia offeso dal fatto che un codice di funzione possa
> essere
> messo in un file .h ed infatti è una cosa che non faccio mai.
non sono offeso, e non ho neanche detto che non funziona, e' una "bad
practice".
> Ma mi sembra di capire che le funzioni inline fanno eccezione, come
> recita
> anche il manuale di GCC:
> --- fromhttp://gcc.gnu.org/onlinedocs/gcc/Inline.html---
SI MA CHISSENEFREGA DI COME GESTISCE GCC LE INLINE. Devi leggerti il
manuale del TUO compilatore perche' magari le gestisce in modo
diverso. Magari (e dico magari visto che non ce lo vuoi dire che
cavolo dicompilatore usi) il tuo compilatore non permette di fare
quello che vuoi tu. Ma l'unico modo per saperlo e' leggere sto fottuto
manuale (RTFM!)
Ciao Jack
Infatti ci avevo pensato, però è un metodo un po' brutto...
> Magari il tuo compilatore ha un flag per disabilitare questo warning di funzione
> definita ma non usata, anche perche' io non l'ho mai visto.
Purtroppo il compilatore permette di definire dei livelli di warning.
Per eliminare
quel warning devo scendere abbastanza in basso ed andrei ad eliminare
parecchi
warning interessanti.
Vabbè, me lo devo tenere così... :(
Beh, da qualche parte bisogna prendere pure spunto... tu dove ti fai
ispirare?
> > Capisco che tu sia offeso dal fatto che un codice di funzione possa
> > essere
> > messo in un file .h ed infatti è una cosa che non faccio mai.
>
> non sono offeso, e non ho neanche detto che non funziona, e' una "bad
> practice".
Lo fanno nel kernel di linux, lo dice il manuale GCC, a questo punto
la
maggior parte dei programmatori usano una "bad practice"...
> > Ma mi sembra di capire che le funzioni inline fanno eccezione, come
> > recita
> > anche il manuale di GCC:
> > --- fromhttp://gcc.gnu.org/onlinedocs/gcc/Inline.html---
>
> SI MA CHISSENEFREGA DI COME GESTISCE GCC LE INLINE. Devi leggerti il
> manuale del TUO compilatore perche' magari le gestisce in modo
> diverso. Magari (e dico magari visto che non ce lo vuoi dire che
> cavolo dicompilatore usi) il tuo compilatore non permette di fare
> quello che vuoi tu. Ma l'unico modo per saperlo e' leggere sto fottuto
> manuale (RTFM!)
Già letto e questo è quello che dice:
---
[General Format]
#pragma inline Function name [, Function name ...]
[Explanation]
Recursively called functions cannot be subjected to in-line
expansion.
It should also be noted that functions may not be subjected to in-
line
expansion depending on asm statement use, structure/union type
argument presence, setjmp function calling, and other conditions.
When there are two or more descriptions for the same translation unit
or in-line expansion is specified by an option, all the specified
function
names are valid.
The in-line expansion specifying is invalid if the -O option is not
specified.
---
Perchè dici che non voglio dirti qual è il mio cavolo di compilatore?
Si tratta di un compilatore della Fujitsu per i suoi microcontrollori
a 16 bit.
> Purtroppo il mio compilatore non è nè C99 né GCC, quindi vuole per
> forza #pragma.
Hai provato come ti è stato suggerito di dichiararle solo nel .h come
static?
#pragma inline
static void foo(void)
{
... // corpo funzione
Non lo dire a Jack, però ;-)
> #pragma inline
> static void foo(void)
> {
> ... // corpo funzione
>
> }
Se includo quel .h in file .c che non usa la foo() il compilatore mi
dà warning
di simbolo statico definito ma non usato. Penso che non ci posso fare
nulla... :(
> Se includo quel .h in file .c che non usa la foo() il compilatore
> mi dà warning di simbolo statico definito ma non usato. Penso che
> non ci posso fare nulla... :(
Più che giusto. Sai come si dice, no? ;-)
"Non puoi avere la botte piena e la moglie ubriaca"
Non so se ti pu� essere di aiuto, ma io faccio cos�:
siccome il mio compilatore non supporta la direttiva inline, allora faccio:
in un file .h
#define foo(par1,par2) ....
questo mi permette di realizare le funzioni inline.
In realtᅵ quello che fai ᅵ definire una macro e non una funzione inline.
Anche se apparentemente ti sembra la stessa cosa (non c'ᅵ nessuna call),
sono due cose diverse.
Se cerchi su Internet troverai i pro e contro delle due soluzioni.