Newsgroup: it.comp.lang.c++
Titolo: Funzioni inline e puntatori

Se faccio puntare un puntatore a funzione ad una funzione inline, e la
chiamo tramite questo, non avviene l'esapansione inline a tempo di
compilazione, ma č chiamata la funzione come se non fosse inline, vero?
--
Marco Iannaccone
marc...@tin.it
ICQ UIN: 18748121     MetalCoder
"This is a new ship, boy, but she's got the right name.
You treat her like a lady, and she'll always bring you home."
    Dr. Leonard H. McCoy to Data - Encounter at Farpoint - Star Trek TNG

 compilazione, ma è chiamata la funzione come se non fosse inline, vero?
Si e no :
In generale un compilatore fara' cio' che gli si richiede (se e' possibile).
Se si chiede una funzione inline questa sara' inline a meno che questo non
sia impossibile oppure non sia del tutto opportuno.
Ad esempio se si usa inline in una funzione ricorsiva, o in una funzione
troppo complicata etc... il compilatore ignorera' semplicemente la keyword
inline e la trattera' come una normale funzione.
Ora il caso in cui si usi un puntatore ad una funzione inline (quello che
chiedi tu) e' uno di questi casi, ma un po' piu' particolare. In sostanza la
funzione è chiamata come se non fosse inline, ma............
Noterai che ti ho scritto si e no. Non ho sbagliato:
Infatti dove il puntatore non e' utilizzato un buon compilatore sara' in
grado di scrivere ancora la funzione come inline.
Per concludere nel caso da te descritto, la funzione sara' sia inline che
normale, dipende da come la chiami !!! Se in un punto la chiami con il
puntatore ed in un altro no, allora una sara' inline e l'altra no! (questo
non e' garantito su tutti i compilatori).
Alex

compilazione, ma è chiamata la funzione come se non fosse inline, vero?
"The compiler also cannot perform inlining if the address of the
function is taken implicitly or explicitly. If the compiler must
produce an address, then it will allocate storage for the function
code and use the resulting address. However, where an address is
not required, the compiler will probably still inline the code."
[Thinking in C++]
In un caso come il seguente :
#include <iostream>
inline void pippo()
{
       std::cout << "hello world!" << std::endl ;
}
int main()
{
    void (*p)() = pippo ; // richiesto indirizzo
    p() ;
    return 0 ;
}
Il compilatore non puo' espandere la funzione.

Grazie! Comunque, chiamando invece la funzione non tramite il puntatore, la
funzione è espansa, no?


 funzione è espansa, no?
Si, nella maggior parte dei casi. Non e' una regola, dipende dal
compilatore.
Alex
P.S. ti avevo gia' scritto:
<QUOTE>
Se in un punto la chiami con il
puntatore ed in un altro no, allora una sara' inline e l'altra no! (questo
non e' garantito su tutti i compilatori).
</QUOTE>

funzione è espansa, no?
Dipende, e' un meccanismo da implementare a discrezione del
compilatore.  La keyword "inline" e' solo un suggerimento.

Il compilatore non puo' espandere la funzione.
Giusta l'idea di fondo ma sbagliato l'esempio.
In questo caso il compilatore e' liberissimo di
espandere la funzione inline.
Anzi.
In base a quello che hai scritto non e' nemmeno
obbligato a generare una versione non-inline
della funzione stessa.
Diverso se tu avessi scritto, ad esempio:
  ...
  void (*p)();
  void foo();
  int main()
  {
    p=pippo;
    foo();
    p();
    return 0;
  }
In questo caso infatti foo() potrebbe voler usare il puntatore
p (quindi p deve essere puntare ad una versione non-inline
della funzione) e potrebbe anche modificarlo (quindi il
compilatore non puo' espandere inline la funzione nel punto
di main() in cui viene chiamata).
Con l'esempio che hai fatto tu, ad esempio, g++ non espande
inline la funzione (come sai a questo non lo puo' obbligare
nessuno) ma *non* usa il puntatore per chiamare la funzione
e fa invece una chiamata normale.
Andrea
--
Andrea Griffini, Programmer
http://www.netservers.com/~agriff

e fa invece una chiamata normale.
Il tuo punto di vista e' giusto, ma allora non mi spiego perche' una
funzione cosi' semplice non viene espansa.

"Andrea Laforgia" <xx...@xxxxx.xxx> wrote in message
news:66luht440jbtgg5b9...@4ax.com...

Dipende dal compilatore. Come ben sai il compilatore non e' affatto obbligato ad
espandere. Che poi spesso gli ottimizzatori si comportino in modo assurdo
espandendo e semplificando casi complicatissimi e rifiutandosi di espandere e
semplificare casi semplicissimi ... questo e' un altro discorso.
Nota che comincino ad esistere compilatori (o meglio sistemi di sviluppo) in
grado di eseguire espansioni inline e ottimizzazioni anche attraverso diverse
TU. O persino in fase di link (e sospetto anche dopo il link!). Quindi potrebbe
persino succedere che:
// foobar.h
inline void foo() {}
typedef void (*PF)();
extern PF ptr;
void bar();
// ptr.cpp
include "foobar.h"
PF ptr=foo;
// bar.cpp
include "foobar.h"
void bar()
{
    foo();
    ptr();
}
// main.cpp
include "foobar.h"
int main()
{
    foo();
    bar();
    return 0;
}
generi esattamente lo stesso codice generato da:
// main.cpp
int main()
{
    return 0;
}
--
Andrea Ferro
---------
Brainbench C++ Master. Scored higher than 97% of previous takers
Scores: Overall 4.46, Conceptual 5.0, Problem-Solving 5.0
More info 
http://www.brainbench.com/transcript.jsp?pid=2522556

semplificare casi semplicissimi ... questo e' un altro discorso.
Ok, il compilatore non e' obbligato e lo sappiamo tutti.  
Inutile ribadirlo.  
Il concetto di fondo e' : il compilatore, in questo caso, non ha
espanso la funzione inline perche' ne ho richiesto l'indirizzo o ha
deciso di non farlo per altri motivi ?
Su tutti i manuali che ho letto, viene indicato il rifiuto da parte
del compilatore di espandere le funzioni inline o quando sono troppo
complicate o per impossibilita' pratiche.
Ora, non credo che la funzione del mio esempio fosse troppo
complicata.
Se scrivo :
#include <iostream>
inline void pippo()
{
       std::cout << "andrea" << std::endl ;
}
int main()
{
    pippo() ;
    return 0 ;    
}
Il gcc di prima (quello che non ha espanso la funzione) come si
comporta ?
E se la espande, non potrebbe essere che prima non l'ha espansa
perche' ne ho richiesto l'indirizzo ?

e fa invece una chiamata normale.
Intanto, pero', non la espande e vorrei capire il perche'.
Quello che io vorrei capire e' se il compilatore non espande la
funzione perche' ha visto che se ne ottiene l'indirizzo o per qualche
altro motivo.
Il BC++ 5.5, per esempio, traduce il seguente codice :
<CODE>
#include <iostream>
inline void pippo()
{
       std::cout << "ciao mondo !" << std::endl ;
}
int main()
{
    pippo() ;
    return 0;
}
</CODE>
in quello esattamente equivalente (ho confrontato attentamente i .ASM
generati) a :
<CODE>
#include <iostream>
int main()
{
    std::cout << "ciao mondo !" << std::endl ;
    return 0;
}
</CODE>
viceversa, quando scrivo :
<CODE>
#include <iostream>
inline void pippo()
{
       std::cout << "ciao mondo !" << std::endl ;
}
int main()
{
    void (*p)() = pippo ;
    p() ;
    return 0;
}
</CODE>
produce (semplificando di molto il .ASM) :
   ;	
   ;	int main()
   ;	
	push      ebp
	mov       ebp,esp
   ;	
   ;	{
   ;	   void (*p)() = pippo ;
   ;	
@1:
	mov       eax,offset @@pippo$qv
   ;	
   ;	
   ;	   p() ;
   ;	
?live16385@32: ; EAX = p
	call      eax
   ;	
   ;	
   ;	   return 0 ;
   ;	
?live16385@48: ; 
	xor       eax,eax
   ;	
   ;	}
   ;	
Il che mi fa pensare che, come afferma il manuale, il compilatore non
abbia espanso la funzione, perche' ha notato che se ne richiede
l'indirizzo.

 perche' ne ho richiesto l'indirizzo ?
Non so il gcc. Ma dagli ottimizzatori ho imparato ad aspettarmi di tutto. Nella
pratica comunque non cambia. Prima scrivi il codice. Poi ottimizza solo quello
che e' strettamente necessario ottiizzare (ammesso che il compilatore non lo
abbia già fatto).


tutto.
Molto interessante.

 semplificare casi semplicissimi ... questo e' un altro discorso.
Verissimo ! I compilatori oggi giorno ottimizzano il codice in modo
spaventoso.
Bjarne Stroustrup dice che alcuni buoni compilatori riescono data la
seguente funzione:
inline int fac(int n)
{
     return (n<2)?1:n*fac(n-1);
}
a lasciarla (in alcuni casi) inline.
La funzione presentata (da Bjarne) calcola ricorsivamente il fattoriale di
un numero. Nonostante la funzione sia ricorsiva, la funzione e' molto
semplice.
Chiamandola fac(n); (dove n magari viene letto da tastiera) la funzione NON
sara' inline. Chimandola invece come fac(6); il compilatore puo' scrivere
inline solo la costante 720 !!!
Questa cosa quando la lessi mi lascio' perplesso !!!
Ovviamente Bjarne dice anche che questo e' a discrezione del compilatore.
Molti compilatori con fac(6); potrebbero ignorare totalmente la parola
inline e considerarla come una normale funzione.
Alex

Questa cosa quando la lessi mi lascio' perplesso !!!
NOOO un genio come te !

O persino in fase di link (e sospetto anche dopo il link!).
Ricordo di aver letto qualcosa di un esperimento HP di compilazione
JIT dal codice di un processore RISC al codice dello *stesso*
processore ottenendo un guadagno interessante in termini di
prestazioni per questioni di miglioramento della localita' del
codice (migliore uso della cache).
(!)


l'indirizzo.
Questa sarebbe un'altra limitazione inventata da BCC55; non
e' sicuramente un limite intrinseco del C++.
Poi, come ovviamente ti sara' chiaro, un compilatore puo'
essere conforme ed ignorare *tutte* le richieste di espandere
inline il codice; basta che accetti la parola 'inline' con le
sue conseguenze (definizioni multiple).


se m e' dichiarata essere una std::map<std::string,std::string>).
Be' su questo bisognerebbe arrabbiarsi con Rogue Wave... Borland non
c'entra :)

 c'entra :)
Completamente in disaccordo. Il compilatore lo ha scritto Borland. Ed e' il
compilatore che decide cosa va espanso inline e cosa no.


compilatore che decide cosa va espanso inline e cosa no.
Leggi meglio : stavamo parlando di std::map.

 Leggi meglio : stavamo parlando di std::map.
Che cosa vuol dire ? E' sempre il compilatore che deve compilare e quindi
cercare di ottimizzare. Non e' la classe stessa che, che ad un certo punto
dice: "stop, ora compilo io" ;-)
Se io ti scrivo la classe CStack che gestisce uno stack, io sono
responsabile del buon funzionamento della classe, non di come esssa venga
compilata.
Il modo in cui viene compilata dipendera' dal compilatore sulla quale viene
utilizzata.
Se utilizzo una funzione inline e su borland viene espansa mentre su
Microsoft no, io che cosa c'entro ?!? Ripeto e' sempre e solo il compilatore
che decide che cosa va espanso e cosa no !
Alex

 se m e' dichiarata essere una std::map<std::string,std::string>).
e deduco che si sta parlando di espansione inline della std::map. Il fatto che
quei 4K sono inline anche se non ha senso non dipende dalla definizione di
std::map ma dall'implementazione del compilatore. Tra l'altro questo e' vero
persino se tutti i metodi della STL sono esplicitamente dichiarati inline (cosa
di cui dubito, anche se non ho visto gli header di Rogue Wave).


compilatore che decide cosa va espanso inline e cosa no.
Aggiungerei qualcosa. Quando il cliente si incazza perche' il tuo
programma crasha non gliene frega molto se il baco e' del VB o
del tuo codice. Comunque non ti paga la fattura (e ha ragione).
Se io compilo codice con il BCC55 e questo codice fa schifo
il problema e' della Borland. Io mica ho imposto che usassero
questa o quella implementazione di STL.
Forse Andrea Laforgia grazie ai superpoteri di "SuperWalkie"
riesce a convincere il cliente a lamentarsi dei problemi con la
Borland quando il suo codice si pianta per un bug del compilatore ???
Sarebbe bello riuscire a farsi mordere dallo stesso ragno
radioattivo !!! :)
Andrea
PS:
  Anzi no. Ho lavorato in ambienti in cui la preoccupazione
  era di fare in modo che la colpa non fosse tua (invece che di
  far funzionare le cose) e questo aspetto l'ho sempre detestato
  anche se credo che sia forse inevitabile al crescere della
  dimensione per via della deresponsabilizzazione.
  Io comunque preferisco vedere le cose che vanno :)


std::map ma dall'implementazione del compilatore.
Hai ragione...

Borland quando il suo codice si pianta per un bug del compilatore ???
A quanto pare non e' possibile discutere con te, senza scendere
necessariamente ai livelli di un flame (ed e' una cosa che ho visto
accadere tra te e molta altra gente).  Mi sa che se continui di sto
passo ti becchi un altro bel *PLONK*.

passo ti becchi un altro bel *PLONK*.
Quella voleva solo essere una nota di colore... visto anche che
ora firmi Laforgia ma con la mail di WalkieTalkie.
Se fossi stronzo ti direi di provare ad indovinare in una scala
da 1 a 10 quanto mi frega se leggi i miei messaggi oppure no...
in realta' un pochino mi interessa: spesso i tuoi commenti sono
sensati anche se ultimamente di ho visto un po' acido in generale.
Andrea


non ci sono con Builder (o magari ci sono lo stesso).
Nella ditta dove lavoro usiamo(uso) il Builder5 Professional(basato
sul BCC55)che sinceramente come prestazioni in generale non mi sembra
affatto male.
Non é da escludere infatti che nella versione gratuita ci siano delle
cose in meno specie dal punto di vista delle ottimizzazioni, ma per
poter affermare un simile cosa avrei bisogno di fare qualche prova in
più.
Il Ghenio
-----
ZIO : Fun and games are over with. Anyone who dares
get in my way shall perish.
-----