Rimuovere una variabile locale

Ciao a tutti.
Modificando il mio contatore Geiger di qualche anno fa mi è sorta una curiosità che è per lo più concettuale...

Premessa:
Giorni fa ho notato che se spegnevo la retroilluminazione (lo stato viene salvato in EEPROM!) e poi mi trovavo in un luogo buio non avevo più modo di fare nulla, neanche ripristinare la retroilluminazione! Ho risolto il problema accendendo la retroilluminazione quando entro nel menu, ma con una variabile devo memorizzarne lo stato precedente.

Il menu è una funzione bloccante (lo feci così, funziona e non ho intenzione di metterci le mani! :slight_smile:), in cui l'esecuzione del programma rimane riservata alle impostazioni.
Se rilevo una pressione prolungata dell'encoder dichiaro una variabile per memorizzare lo stato della retroilluminazione, poi vene eseguito il menu e quando riesce imposta nuovamente la retroilluminazione così come era in precedenza. A questo punto la variabile non è più necessaria fino al prossimo giro di loop: posso rimuoverla?

Non so se questa domanda abbia senso, oppure mi è nata solo perché sto usando una variabile locale in maniera sbagliata...

L'IDE, da parte sua, rileva qualcosa di incomprensibile...

C:\Users\giobb\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.3\cores\arduino\main.cpp: In function 'main':
E:\Documenti\@ ELETTRONICA\Arduino\@  4 Contatore Geiger OK R\GEIGERINO_v1.14e\d_Loop_prImpRad_portate.ino:21:29: warning: 'stato_retroill' may be used uninitialized in this function [-Wmaybe-uninitialized]
     if (LCD==2) digitalWrite(A0, stato_retroill); // SE LCD è in modo On/Off, ripristina lo stato precedente.
                             ^
E:\Documenti\@ ELETTRONICA\Arduino\@  4 Contatore Geiger OK R\GEIGERINO_v1.14e\d_Loop_prImpRad_portate.ino:9:13: note: 'stato_retroill' was declared here
     uint8_t stato_retroill;
             ^

Grazie
Gianluca

Allego la parte del codice:

void loop()
{ // PIND&0x20)>>5 è come dire digitalRead(5).
P=(PIND&0x20)>>5; // Legge il pulsante dell'encoder (0=Premuto)
if(Po==1 && P==0) {t1=millis(); Po=0;} // Quando viene premuto il pulsante legge il tempo
if(Po==0 && P==0)     // Se era ed è premuto per almeno 1 secondo
  {                   // salta a Menu, poi ritorna ed esce.
  if(millis()-t1>999) // 
    {
    uint8_t stato_retroill;
    if (LCD==2) 
      {
      stato_retroill=digitalRead(A0);
      digitalWrite (A0, LOW); // Se LCD==2 (retroilluminazione in modo On/Off), accende la retroilluminazione.
      }
    Po=1; Bip();
    detachInterrupt(0); // Blocca gli interrupt per evitare che si accumulino conteggi
    Menu();             // che poi verrebbero divisi per un tempo brevissimo, non essendo
    while(!(PIND&0x20)) // stata, nel frattempo, incrementata la variabile tempo.
    delay(200);
    Mask();
    if (LCD==2) digitalWrite(A0, stato_retroill); // SE LCD è in modo On/Off, ripristina lo stato precedente.
    attachInterrupt(0,ContaAB,FALLING); return;
    }
  } // END premuto per almeno 1 secondo

// ... ... ...

} // END loop()

... se è una variabile "locale" che crei ne loop(), quando il loop() finisce automaticamente viene eliminata.

Guglielmo

Sì, certo, ma mi chiedo se sia possibile eliminarla subito dopo che si è finito di usarla, quando nella funzione non serve più, prima di uscire dalla funzione. Potrebbe essere utile per un array voluminoso... ma forse la mia domanda non ha senso perché appena finito di usare l'array voluminoso basta chiudere la funzione e proseguire con un'altra...

Si, si può fare, si chiama allocazione dinamica della memoria e di usano le funzioni di libreria:

Se li cerchi trovi proprio esempi di malloc() per array da liberare dopo l'uso :wink:

Guglielmo

Piccolo tutorial sul funzionamento di malloc() :wink:

Guglielmo

malloc() è una funzione che alloca spazio nel "heap" ... se occorre allocare spazio nello "stack" si può usare la macro alloca() (che sta in <alloca.h>) ...

malloc-std

... la grossa differenza è che si può solo allocare e lo spazio viene rilasciato quando la funzione che lo ha occupato va a termine.

Guglielmo

Grazie, Gugliemo :slight_smile:
Con malloc() undeclare variable, finalmente con Google ho trovato anche questo:

in cui giustamente dice che basta creare un piccolo scope interno con {}. Tra l'altro, nel mio caso particolare, mi rendo conto ora che la variabile esiste solo all'interno di

  if(millis()-t1>999)
    {
    // ...
    }

che va poco oltre l'uscita dal menu.
Comunque leggerò volentieri il tutorial! :slight_smile:
Grazie

... ogni variabile LOCALE viene distrutta all'uscita dal blocco che l'ha creata :wink:

Guglielmo

P.S.: malloc() è quello che usa internamente la classe String che appunto ... su piccole MCU può creare problemi.

Sì, però siamo abituati a mettere le graffe (nemmeno sempre!...) solo per una funzione o un if o un for o altro. Lì, invece, suggeriscono di aggiungerle solamente per delimitare l'esistenza della variabile.

... ciascuno parli delle SUE cattive abitudini :joy: :joy: :joy:

Guglielmo

:joy:
Premesso che il problemino ormai è risolto...
Con malloc() dovrei usare un puntatore alla variabile?
Delete mi sembra fatto apposta... No?...

Quello però è C++ ... :roll_eyes: ... quello che ti ho scritto prima è 'C' dove non esistono né la new() né la delete().

Guglielmo

E allora, con le mie di cattive abitudini, non mi basta la "vita utile" delle corde vocali...

Ti aspettavo, Standardoil! :slight_smile:
Quanto ci fai con un Mi cantino? :smile:

Non sapevo nemmeno esistesse, una cosa con quel nome...

Con le Alabastro di Aquila corde ci faccio 6 mesi.

:smile:

:slight_smile:

Il delete() o il Mi cantino?...

P.S.: con la chitarra ho solo minime esperienze... La mia mano sinistra proprio non ci si trova! :frowning:
A cambiare le corde e accordarla, anche a orecchio, me la cavo bene. Ho studiato pianoforte e piano jazz per alcuni anni.

Il mi cantino

Il delete lo conoscevo

Anche se in C si usa malloc() calloc() realloc() e free() non delete

New() e delete sono di C++

Ma nrl tuo caso sono c ompletamente inutili se non addirittura deleteri

Usa tranquillo l'allocazione automatica regolando bene lo scope

La mano sinistra soffre per tanti motivi, ma sostanzialmente soffre perché è chiamata a fare un lavoro in una posizione innaturale. Poi con l'età mi si addormenta pure, ma l'amore per questo strumento è viscerale.

Anche io preso lezioni di piano e da ragazzino sono finito in una TV locale a suonare il Valzer del Danubio. :smiley:

Riguardo al blocco di codice libero l'uso è raro, si usa meno raramente nelle librerie per limitare l'uso dello stack. Ovviamente se ci si ritrova nelle condizioni di dovere usare tante variabili di appoggio per dei calcoli che non servono più nel proseguo della funzione male non fa racchiuderle in un blocco libero. Siccome si può fare if (true) {} è permesso anche il blocco libero.

Ciao.

Che bella amichevole discussione variegata!
Grazie! :slight_smile: