Ho una domanda da porre, e spero che chi si intende di programmazione e gli 'esteti' possa delucidarmi.
E' meglio uno switch o più if??
Ho scritto questo
if (eventi[i] == 1) {
bitSet(buffer_uscite, i - 6);
}
if (eventi[i] == 2 || eventi[i] == 0) {
bitClear(buffer_uscite, i - 6);
eventi[i] = 0;
}
E poi con la funzione switch ho scritto questo
switch ( switch (eventi[i]) {
case 0:
bitClear(buffer_uscite, i - 6);
break;
case 1:
bitSet(buffer_uscite, i - 6);
break;
case 2:
bitClear(buffer_uscite, i - 6);
eventi[i] = 0;
break;
}
Fanno entrambe la stessa cosa, ma quale mi consigliate di usare come forma?
Quale delle due espressioni è più veloce?
Ho identato meglio...
Mah, non ho a disposizione il materiale per provare (con questa storia del covid le consegne si sono allungate), ma sulla carta mi sembrano se non uguali....simili...cioè il risultato finale mi sembra lo stesso...
O sbaglio??
Sbagli, due programmi simili non fanno la solita cosa
a = a + 1;
a = a -1 ;
sono molto simili ma fanno due cose diamtralmente differenti.
Così i due pezzi di codice (che penso siano stati trovati su internet piuttosto che scritti da zero da te) fanno cose differenti poiché il secondo if ha due condizioni in or, cosa che lo switch non ha ovviamente
Quello che hai scritto non è uguale perchè nel primo case (quello a 0) NON hai messo eventi[ i ] = 0;
Ora, il if con l'or lo puoi fare con switch, basta che usi il break; in maniera "creativa", ovvero sfrutti il fatto che il case è punto di ingresso ma solo il break fa "uscire" dal case, se non c'e' prosegue:
switch ( eventi[i])
{ case 1:
bitClear(buffer_uscite, i - 6); // entro con 1 ed esco
break;
case 0: // entro con 0 ma proseguo nel 2
case 2: // entro con 2
bitClear(buffer_uscite, i - 6);
eventi[i] = 0;
break;
}
Per la tua domanda... quale più veloce... nessuna delle due, tanto il codice C viene convertito in assembly, con una serie di jump condizionati, ottimizzati dal compilatore ; probabilmente il risultato tra i due in linguaggio macchina è molto simile
manolomao:
Fanno entrambe la stessa cosa, ma quale mi consigliate di usare come forma?
Farebbero la stessa cosa se non avessi dimenticato di scrivere eventi[i] = 0; anche nel case 0.
Ma non sarebbero lo stesso la stessa cosa perché i case di uno switch sono (normalmente) mutuamente esclusivi, la forma con l'if avrebbe dovuto proseguire con else if, non con un altro if indipendente dal primo.
Oltre a questo i vari case dello switch testano solo l'uguaglianza con un valore intero, non condizioni più complesse che si possono testare solo con if.
Su quale usare, secondo me quella che di volta in volta nel caso specifico è più chiara da leggere/modificare.
Claudio_FF:
Oltre a questo i vari case dello switch testano solo l'uguaglianza con un valore intero, non condizioni più complesse che si possono testare solo con if.
Questo molto importante, gli if possono avere dei test molto complessi, lo switch solo uguaglianza su numeri interi
In pratica se devi confrontare solo dei valori interi, esempio verificare se sia 1,2,3,4 ecc.. meglio usare uno switch(), altrimenti usare un if e else if.
La struttura di controllo switch() non è indispensabile ma spesso rende il codice più leggibile.
fabpolli:
Così i due pezzi di codice (che penso siano stati trovati su internet piuttosto che scritti da zero da te) fanno cose differenti poiché il secondo if ha due condizioni in or, cosa che lo switch non ha ovviamente
Mi spiace, ma i due pezzi di codice li ho fatti io di sana pianta, senza copiare nulla...
Comunque mi è chiaro il discorso, quello che volevo sapere mi è stato spiegato molto bene da nid69ita, ho capito che i tempi di esecuzione sono simili e questo mi basta...
Anche l'idea creativa dello switch è davvero...creativa.....
Grazie davvero per le spiegazioni.
questo è errato: switch ( switch (eventi[ i ] ) {
questo è corretto: switch ( eventi[ i ] ) {
ovviamente non serve ma mi sono concentrato sul portare paro-paro gli if in switch
anche la biClear è uguale in tutti e 3 i case, si potrebbe ottimizzare, ma non era l'argomento
Beh, scusa il punto 1 era un chiaro errore di copia incolla che è venuto il doppio switch...
Per il punto 2, nel case 1 è un bitSet e non un bitClear...
Cmq grazie per l'aiuto.
grazie, mi è chiaro...
volevo sottoporvi un altro problema...in questi giorni ho del tempo da usare per apprendere.
Ho bisogno di controllare 6 PWM, e per temporizzare ogni step ho utilizzaro la libreria MsTimer2.
Non ho dubbi su come usarla ma su come migliorare il controllo dello start e dello stop.
In pratica ho delle variabili boolean che mi dicono se il PWM sta salendo o scendendo racchiuse in due array
boolean fade_up[6]
boolean fade_dw[6]
ora per far partire la libreria il comando da usare è
MsTimer2::start();
mentre per farla disattivare il comando è
MsTimer2::stop();
Quindi mi trovo che se almeno una delle variabili fade_up e fade_dw è vera parte il timer
if ((fade_up[0])||(fade_up[1])||(fade_up[2])||(fade_up[3])||(fade_up[4])||(fade_up[5])) {MsTimer2::start();}
if ((fade_dw[0])||(fade_dw[1])||(fade_dw[2])||(fade_dw[3])||(fade_dw[4])||(fade_dw[5])){MsTimer2::start();}
Se tutte le variabili fade_up e fade_dw sono false il timer si spegne
if ((!fade_up[0])&&(!fade_up[1])&&(!fade_up[2])&&(!fade_up[3])&&(!fade_up[4])&&(!fade_up[5])&&
(!fade_dw[0]) &&(!fade_dw[1])&&(!fade_dw[])&&(!fade_dw[3])&&(!fade_dw[4])&&(!fade_dw[5])){MsTimer2::stop();}
Lasciando perdere l'identazione (me ne scuso....), esiste una scrittura migliore per fare quello che voglio fare?
Grazie.
Questa istruzione precisamente come si comporta??
perchè io ho due array , uno è fade_up e l'altro è fade_dw...
se uno solo è vero parte il timer, se tutti sono falsi ferma il timer.....
Grazie per l'aiuto
manolomao:
perchè io ho due array , uno è fade_up e l'altro è fade_dw...
se uno solo è vero parte il timer, se tutti sono falsi ferma il timer.....
Attenzione che qui le parole sono importantissime:
Se uno solo, oppure se almeno uno? Fa la differenza tra uno XOR e un OR. Il codice che hai scritto rappresenta un OR, quindi "se almeno uno".
Parte il timer, oppure RIparte il timer? Fa la differenza tra un timer singolo impulso e uno retriggerabile.
Non conosco la libreria , ma se MsTimer start fa RIpartire il timer, e non solo partire, allora non capisco a cosa serva, perché il timer sarà sempre in conteggio, per fermarsi solo quando tutti gli elementi degli array saranno falsi. In sostanza, cosa dovrebbe fare quel timer? Vedo qui al paragrafo Example. Start attiva gli interrupt di MsTimer dopo che in precedenza si è settato il periodo.
Questa istruzione precisamente come si comporta??
È una funzione che restituisce l'OR tra gli elementi dell'array passatole, se tutti gli elementi sono falsi restituisce falso, altrimenti se almeno uno e` true restituisce true. Usando la funzione il tuo codice completo sarebbe:
if (any(fade_up) || any(fade_dw) { MsTimer2::start(); } // start se almeno un elemento true
else { MsTimer2::stop(); }
Il discorso a margine era incomprensibile perché mi era saltato un pezzo...
Dicevo che quando devo gestire qualcosa con più fasi, scrivo le fasi esplicitamente, con le condizioni di passaggio da una all'altra, compresi eventuali timeout calcolati con millis:
switch (fase){
case 30:
....
if (...condizione cambio fase...) { fase = ...; }
break;
case 10:
....
if (...condizione cambio fase...) { fase = ...; }
break;
case 65:
....
if (millis()-inizio > 10000) { fase = ...; } // timeout 10s
break;
}