Newsgroup: it.comp.lang.c
Titolo: efficienza switch

Secondo voi e' piu' efficiente questo codice:
inline void state0() {
   ...
}
inline void state1() {
   ...
}
...
void loop() {
   int state=0;
   ...
   switch(state) {
     case 0:
       state0();
     break;
     case 1:
       state1();
     break;
     ...
   }
}
Oppure questo:
void state0() {
  ...
};
void state1() {
  ...
};
void loop() {
   void (*state)()= &state0;
   ...
   state();
}
Nel secondo caso non ha piu' senso utilizzare funzioni inline, e si 
perde quindi del tempo nella chiamata alla funzione.
Nel primo caso dipende forse da come viene implementato lo "switch"... 
puo' essere che se i "case" sono valori consecutivi il compilatore sia 
tanto furbo da fare una tabella?
E.

 tanto furbo da fare una tabella?
Il compilatore di solito e' abbastanza furbo da fare una
tabellina con i case se pensa che questo gli possa
portare un giovamento.
Comunque mi aspetto un differenza veramente minima tra le
due soluzioni, a meno che il codice delle due funzioni
sia proprio minimo.
A priori e' anche difficile capire
come si comportera' il compilatore, la cache, etc. etc.
L'unica cosa che mi sento di dire su due piedi e' che
in particolari circostanze se usi le funzioni inline
allora il compilatore potrebbe fare delle ottimizzazioni
globali che coinvolgono i codici di entrambe le funzioni,
mentre se sono funzioni separate non dovrebbe.
In ogni caso temo che dovresti fare la prova col
tuo codice, sul tuo compilatore, sul tuo hardware,
per avere la certezza.
ciao,
g.

 per avere la certezza.
Ok, temevo questa risposta... trovo molto difficile fare i test. In 
realta' immagino anch'io che la differenza sia minima. Per dirla tutta 
il fatto e' questo. Il codice e' gia' scritto con switch e funzioni 
inline (per la cronaca le funzioni sono molto lunghe, ma vengono 
chiamate solo dallo switch, quindi e' sensato dichiararle inline). 
Funziona bene, non credo ci siano problemi di efficienza. Solo che per 
la leggibilita' e per ridurre i sorgenti avevo pensato di convertirlo 
all'altra soluzione. Infatti ora la struttura e' questa:
enum {STATE_PIPPO, STATE_PLUTO, ....} state;
...
void pippo_state() {
   ...
}
void pluto_state() {
   ...
}
...
switch(state) {
   case STATE_PIPPO:
     pippo_state();
   break;
....
}
per aggiungere un nuovo "state" bisogna scriverne il nome quattro volte! 
  Mentre con i puntatori e' piu' elegante, e basta scrivere il nome una 
volta sola....
E.

 chiamate solo dallo switch, quindi e' sensato dichiararle inline). 
Se le funzioni hanno un codice abbastanza lungo allora
il vantaggio di risparmiare una chiamata di funzione
dovrebbe essere insignificante.
Inoltre, alcuni compilatori pongono delle limitazioni
alle funzioni che possono effettivamente essere
gestite come inline. Per esempio alcuni possono escludere
quelle che contengono cicli o istruzioni condizionali.
Se il problema e' piu' che altro stilistico sono l'ultima
persona che puo' consigliarti, passo.
ciao,
g.

 dovrebbe essere insignificante.
Giustamente... penso che riscrivero' il codice con i puntatori a funzione.
E.


ma si', dai! :) ...non e' difficile con un modello del tipo (eg.):
#include <stdio.h>
typedef void (*pf_state)(void);
static void pippo_state(void)
{	printf("pippo_state()\n");
}
static void pluto_state(void)
{	printf("pluto_state()\n");
}
int main(void)
{
         typedef enum { STATE_PIPPO, STATE_PLUTO, /* ...., */ 
STATE_MAXDIM } t_state;
         pf_state apfStates[STATE_MAXDIM];
         t_state state;
	/* inizializzazione */
         for(state = 0; state < STATE_MAXDIM; i++)
                 apfStates[state] = NULL;
         /* assegnazione */
         apfStates[STATE_PIPPO] = pippo_state;
         apfStates[STATE_PLUTO] = pluto_state;
         /* .... */
         state = STATE_PIPPO; /* stato di esempio */
         /* .... */
         /* verifica e chiamata */
         if(state >= 0 && state < STATE_MAXDIM && apfStates[state])
                 (*apfStates[state])();
         else	/* errore */;
         /* .... */
         return 0;
}
Ciao
-- 
Cybertoldo
Per rispondermi via email, sostituisci moc.liamg con 
gmail.com

         for(state = 0; state < STATE_MAXDIM; i++)
	for(state = 0; state < STATE_MAXDIM; state++)
