[RISOLTO] dichiarare variabili al momento che servono oppure no

Naturalmente, mi sono accorto che “dichiarando” le variabili all’inizio del programma, (prima della funzione SETUP), mi implica un “impegno di memoria”. Se li dichiaro quando mi servono, quindi dentro i void oppure in genere nel listato, la memoria utilizzata NON viene intaccata. Secondo VOI è la stessa cosa dichiararle prima o quando mi servono? oppure quando vengono dichiarate all’occorrenza la memoria si “occupa” e dopo si “libera”? Spero di essermi spiegato. Grazie

Le variabili locali (quelle dichiarate nelle funzioni) vengo allocate entri nella funzione e deallocate quando la funzione finisce.

Occhio però. Esempio hai 4 variabili int (2 byte l’una) e quindi 8 bytes:

  1. Se dichiari globali occupano sempre 8 bytes.
  2. Se la funzione in cui la dichiari è la loop() che è sempre eseguita… non cambia molto come occupazione. In pratica essendo la loop() sempre eseguita, non c’e’ quasi mai “praticamente” un momento in cui non occupi 8 bytes.
    Inoltre uno sketch Arduino in realtà è circa (è nascosta la cosa):
void main()
{ setup();
   while(1) { loop(); }
}

Quindi se dichiari in loop, hai un continuo alloca/dealloca nello stack (anche se operazione che non porta via molto tempo, un calcolo per lo spazio da riservare in stack x var locali)

Ricorda poi che le variabili locali non sono inizializzate a zero.

quindi conviene allocarle/dichiararle dentro la funzione, cosi poi la memoria ritorna libera?

Normalmente si.

Occhio però che se occupi in memoria globale 100 byte e poi nella loop() altri 100 byte, in compilazione ti viene detto che occupi 100 byte. Il compilatore non sa che occuperai altri 100 byte con allocazione di variabili locali. In fase di esecuzione quando sei nella loop() quindi occupi 200 byte e con solo 2Kb di SRAM è facile consumare tutta la memoria (arduino con atmega 328)

Grazieeeeeeeeee

dipende dall’uso che ne devi fare, io non sceglierei il punto dove dichiararle in base a questi aspetti, ma all’uso che ne devi fare.
A meno che le prestazioni rincorse in modo maniacale non siano fondamentali, cioè dove devi recuperare e ottimizzare ogni singolo ciclo macchina…
Se le dichiari dentro la funzione hanno vita locale, si dichiarano quando non devono mantenere il valore tra un ciclo e l’altro. Si dichiarano fuori se devi memorizzare valori che devono sopravvivere al singolo ciclo di loop.

Se poi decidi di dichiararle fuori perchè ti piace di più o per altri motivi legittimi, ma devono avere vita locale al loop, le devi re-inizializzare ad ogni loop, resettare alla fine o inizializzare prima del loro utilizzo, altrimenti rischi di avere valori sporchi che ti alterano l’esecuzione.

No una variabile locale è una variabile globale Sono due cose distinte in quanto 1) nelle variabili globali può non essere dato un valore iniziale in quanto prendono come inizio Zero, Mentre se uso una variabile locale devo in sede di dichiarazione darle un valore se no il valore di quella variabile sarà sbagliato ( corrispondente al valore che quel pezzo di memoria ha avuto la volta precedente che venne usato). 2) Una variabile globale Può essere utilizzata senza problemi in ogni parte del programma Mentre una locale va Passata come parametro per ogni funzione che la utilizza 3) in sede di compilazione io conosco l'intero volume occupato dalle variabili globali ma non ho nessuna idea su quello che occuperanno le locali.

Ove possibile, le variabili LOCALI sono da preferire alle variabili globali.

Vi consiglio un attento studio dell’allegato documento di Atmel relativo alla ottimizzazione del codice. :wink:

Guglielmo

Atmel - Tips and Tricks to Optimize Your C Code for 8-bit AVR Microcontrollers.pdf (237 KB)

Il No è riferito a me?

Silente: No una variabile locale è una variabile globale Sono due cose distinte in quanto

Ovvio, io non volevo dire che una variabile dichiarata fuori era locale o cose di questo tipo ma, essendo un po' più precisi per non fraintendersi: usare una variabile globale al posto di una locale quando nel programma ne basta una locale.

Silente: 1) nelle variabili globali può non essere dato un valore iniziale in quanto prendono come inizio Zero, Mentre se uso una variabile locale devo in sede di dichiarazione darle un valore se no il valore di quella variabile sarà sbagliato ( corrispondente al valore che quel pezzo di memoria ha avuto la volta precedente che venne usato).

In genere il compilatore in questi casi da errore, quindi è implicito tutto questo discorso. Mi fai venire il dubbio su Arduino, visto che lo hai accennato e io inizializzo sempre di prassi, non penso di averlo mai verificato nella pratica, ma in altri linguaggi c'è errore in compilazione.

Silente: 2) Una variabile globale Può essere utilizzata senza problemi in ogni parte del programma Mentre una locale va Passata come parametro per ogni funzione che la utilizza

Questo dovrebbe far parte della progettazione, ovvio che se ti serve globale non la dichiari locale, ma se ti serve locale la puoi sempre dichiarare globale, ma ti tiri dietro le eventuali conseguenze... cioè devi sapere quello che fai e i problemi in cui puoi incappare...

Silente: 3) in sede di compilazione io conosco l'intero volume occupato dalle variabili globali ma non ho nessuna idea su quello che occuperanno le locali.

Si, però questo non dovrebbe essere una discriminante per farti dichiarare tutto globale. Anche perchè per sapere l'ammontare all'inizio hai un enorme spreco sul codice. Puoi dichiarare variabili locali ovunque, non solo dentro il loop ma anche dentro tutte le tue procedure/funzioni/metodi o come le vogliamo chiamare. Dichiari tutto globale per sapere quanto occupano? direi proprio di no o sbaglio?

Se il NO non era riferito a me... pecà, ho solo chiarito meglio il mio pensiero... inutilmente ...

EDIT (causa concomitanza): @gpb01 sei un mito, mi esci sempre con il doc giusto al momento giusto. me lo leggo mooolto volentieri ;)

maubarzi: @gpb01 sei un mito, mi esci sempre con il doc giusto al momento giusto.

:D :D :D ... ho un ampia biblioteca ;)

Guglielmo

e la bontà d'animo di condividerla sempre ;)

gpb01: Vi consiglio un attento studio dell'allegato documento di Atmel relativo alla ottimizzazione del codice. ;)

meraviglia grande Guglielmo, grazie Guglielmo, gagliardo Guglielmo e vai pure avanti tu.....https://www.dizy.com/it/aggettivi/g ho piacevolmente scoperto che anche Atmel va piu' veloce coi de-contatori, piuttosto che coi contatori mi ricorda tanto la mia vecchia Texas......... però mi viene un dubbio, se per usare variabili locali invece che globali sono costretto a passare più parametri piuttosto che restituire strutture?

Standardoil: ... se per usare variabili locali invece che globali sono costretto a passare più parametri piuttosto che restituire strutture?

... beh ... "Est modus in rebus" ;)

Guglielmo

gpb01: Ove possibile, le variabili LOCALI [u]sono da preferire[/u] alle variabili globali.

Vi consiglio un attento studio dell'allegato documento di Atmel relativo alla ottimizzazione del codice. ;)

Guglielmo

Veramente interessante! Chi si "prende la briga" di verificare come riportare i trucchi anche nella programmazione tipica di arduino?

Standardoil: però mi viene un dubbio, se per usare variabili locali invece che globali sono costretto a passare più parametri piuttosto che restituire strutture?

Mah... anche questo approccio mi convince poco. O meglio, il numero di parametri di una funzione non dovrebbe influenzare la scelta di usare variabili globali o locali. Poi concordo sul fatto che sia difficile stabilire dove sia la linea di confine...

Però tendenzialmente si dovrebbe praticamente sempre poter stabilire un contesto di validità delle variabili e quindi si potrebbe passare quello e da li accedere alle variabili che servono, senza doverle dichiarare per forza globali. Riformulo ribaltando l'ottica, ci sono sempre ambiti dove certe variabili non servono proprio e permetterne l'accessibilità (quindi anche la modificabilità) potrebbe causare solo problemi.

A prescindere… io le variabili globali si dichiaro all’inizio del programma è mi servono per tutto il programma.
le variabili locali li definisco sono in quel void dedicato, quindi dovrei risparmiare memoria, giusto?

vi allego un file di quello che ho fatto di arduino (1 ardu per antifurto) (1 ardu per caldaia, quindi temperature casa) (X ardu per ogni 14 controlli, ho circa 5 ardu in casa) (Y per controllo consumi a dare priorità ai vari elettromestici)

nel file allegato quello scritto in rosso è ancora da completare… ahimè
è oltre un anno che faccio aggiornamenti e ampliamenti

DESCRIZIONE.doc (63.5 KB)

informazioni molto interessanti e utili. Se posso fare una considerazione di carattere piu generale, mi verrebbe da dire che se devo stare a contare il programma sul filo dei byte -e lo sto facendo proprio in questi giorni, ho saturato la memoria di un AT 32u4 (arduno pro micro), mi sono letto i documenti che avete citato e ho applicato tutte le strategie possibile , ma niente, non ci sta dentro-, meglio cambiare processore.

Ho perso un sacco di tempo, sacrificato funzioni, ecc. per cui mi sa che passo a un STM32F01.

Voglio dire che arduino , come ogni altro, oltretutto con poco spazio residuo rischia di funzionare anche male. Bisognerebbe sempre secondo me scrivere scketch avendo sempre almeno il doppio dello spazio che serve. IMHO

Hai letto il file allegato DESCRIZIONE.DOC, hai visto quante cosa faccio per singolo arduino mega… Mi sa che stai facendo come me all’inizio della stesura… Usavo troppe variabili e troppi sottoprogrammi inutili.
TU CON ARDUINO COSA STAI FACENDO?

dr_vagus: Ho perso un sacco di tempo, sacrificato funzioni, ecc. per cui mi sa che passo a un STM32F01.

... senza buttare via tutto e riscrivere il codice per passare a differente MCU, la strada più semplice è semplicemente cambiare la MCU restando su AVR ... ATmega 1284P o ATmega2560 ;)

Guglielmo

P.S.: se hai problemi di spazio, per entrambe le MCU si trovano schedine già pronte molto piccole ...

stavo giusto in questi giorni iniziando a guardarmi attorno riguardo un'estensione di SRAM, ho trovato un chip da 1M a un paio di euro, si connette in modo seriale per cui non servono tutti i pin del classico indirizzamento parallelo. Tutto il grosso dei dati e delle variabili possono finire li lasciando solo il programma e le allocazioni strettamente necessarie alla singola operazione sulla memoria principale. Poi non so (non ho ancora approfondito) se ci sono meccanismi per poter spostare su SRAM anche parte del codice.