Newsgroup: it.comp.lang.c
Titolo: #pragma inline

Il mio compilatore non supporta la direttiva inline, ma prevede una
#pragma inline.
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?

 modo di evitare questo warning?
I warning vengono dati a ragione, se sai quel che fai e perch� lo fai
puoi ignorarli

 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

 }
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

 inserire il codice.
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.

 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

 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/
 >

 
Giusto, ho risposto prima di pensare :(

Spero di poter emanare un po' di luce sul concetto di funzione inline, in particolare in C99 e usando i tool GNU.
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.

 inline?
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.

 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.

 inline senza generare warnings ne dalla compilazione ne dal linker.
Purtroppo il mio compilatore non è nè C99 né GCC, quindi vuole per
forza
#pragma.

 --- 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

 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ì... :(

 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.

 forza #pragma.
Hai provato come ti è stato suggerito di dichiararle solo nel .h come 
static?
#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... :(

 non ci posso fare nulla... :(
Più che giusto.  Sai come si dice, no?    ;-)
"Non puoi avere la botte piena e la moglie ubriaca"


> Qual � la tecnica giusta per utilizzare le funzioni inline?
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. 

 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.