Variabili e memoria

Salve a tutti,

vi vorrei chiedere aiuto riguardo la dichiarazione di variabili, ho trovato uno sketch su internet che dichiara delle variabili in questo modo

P(pippo)

e le stampa in questo modo

server.printP(pippo)

dove

server

e' un'istanza dell'oggetto

WebServer

Libreria Webduino.

Mi son reso conto di avere molta confusione in testa, mi potete aiutare a capire come e dove vengano salvate le variabili e che altre memorie ci sono? Ho letto di stack e heap ma non ho capito molto...

Sono più confuso di te.
Potresti mettere il link dello sketch che hai trovato?

eccolo qua:

http://webduino.googlecode.com/svn-history/r29/trunk/examples/Web_Parms_1/Web_Parms_1.pde

Ho fatto questa prova: ho controllato la dimensione dello sketch caricato con le seguenti variabili

P(Page_start) = "<html><head><title>Web_Parms_1 Version " VERSION_STRING "</title></head><body>\n";
P(Page_end) = "</body></html>";
P(Get_head) = "<h1>GET from ";
P(Post_head) = "<h1>POST to ";
P(Unknown_head) = "<h1>UNKNOWN request for ";
P(Default_head) = "unidentified URL requested.</h1>
\n";
P(Raw_head) = "raw.html requested.</h1>
\n";
P(Parsed_head) = "parsed.html requested.</h1>
\n";
P(Good_tail_begin) = "URL tail = '";
P(Bad_tail_begin) = "INCOMPLETE URL tail = '";
P(Tail_end) = "'
\n";
P(Parsed_tail_begin) = "URL parameters:
\n";
P(Parsed_item_separator) = " = '";
P(Params_end) = "End of parameters
\n";
P(Post_params_begin) = "Parameters sent by POST:
\n";
P(Line_break) = "
\n";

dopo ho provato a rimuovere tutte queste variabili e ricaricare lo sketch per controllare la dimensione, risultato: la dimensione dello sketch e' la stessa, quelle variabili non gravano sulla memoria (chissa quale :roll_eyes:) dove viene caricato lo sketch.

Arduino, o meglio l'ATMEGA328, ha due distinte memorie, una è di tipo flash ed è quella dove viene inserito lo sketch, previa compilazione, e le costanti, alcune in modo automatico altre tramite apposite direttive per il compilatore.
La seconda memoria è la ram ed è qui dove vengono poste tutte le variabili, sia quelle di sistema che quelle utente, quando compili l'IDE ti indica solamente l'uso della memoria flash che è indipendente dalla quantità di ram utilizzata, è influenzato solo dalla dimensione del programma (= numero di istruzioni) e dalla quantità di costanti, p.e. le scritte inserite in modo esplicito nella serial.print().

quindi

P(pippo)

salva pippo nella RAM? per questo non occupa spazio nella flash?

amacbr:
quindi

P(pippo)

salva pippo nella RAM? per questo non occupa spazio nella flash?

no, al contrario. Le stringhe tendono a riempire la già scarsa ram, quindi si usa salvale su flash in modo da lasciare più ram alle variabilic del codice

e come si spiega che la dimensione occupata dalla flash non cambia se io tolgo la definizione delle variabili?

non so, forse vengono salvare a runtime, all'avvio del micro?

amacbr:
e come si spiega che la dimensione occupata dalla flash non cambia se io tolgo la definizione delle variabili?

Se vengono assegnate ma non vengono comunque referenziate dal nessuna parte sul codice il compilatore credo le mandi a fà n....
Una sorta di ottimizzazione la fà anche con le variabili e le funzioni non utilizzate.

Ho trovato le definizioni in http://webduino.googlecode.com/svn-history/r29/trunk/webduino/WebServer.h

// declare a static string
#define P(name)   static const prog_uchar name[] PROGMEM

Che mi sa fa la stessa cosa della funzione F dell'IDE 1.x

e poi questo

void WebServer::printP(const prog_uchar *str)
{
  char ch;
  while ((ch = pgm_read_byte(str++)))
    print(ch, BYTE);
}

niki77:

amacbr:
e come si spiega che la dimensione occupata dalla flash non cambia se io tolgo la definizione delle variabili?

Se vengono assegnate ma non vengono comunque referenziate dal nessuna parte sul codice il compilatore credo le mandi a fà n....
Una sorta di ottimizzazione la fà anche con le variabili e le funzioni non utilizzate.

Giusto, ma una dichiarazione di questo tipo P(pippo) non occupa neanche spazio nella memoria del programma, mentre se dichiaro int pippo, se pippo non e' utilizzatto non verra allocata memoria ma lo spazio nella memoria del programma lo occupa. Per memoria del programma intendo dove vengono salvate le istruzioni del programma.

Allora, facciamo un pò di chiarezza...

Il tuo P(pippo) non arriverà mai al compilatore, perchè P non è una funzione, ma è una macro

// declare a static string
#define P(name) static const prog_uchar name[] PROGMEM

quindi il tuo P(pippo) = "etcetcetc" suonerà in fase di compilazione come :

static const prog_uchar pippo[] PROGMEM "etcetcetc"

in fase di ottimizzazione, non vedendo in alcun modo pippo utilizzato , quest'ultimo viene scartato in quanto non serve ad una mazza.

, se pippo non e' utilizzatto non verra allocata memoria ma lo spazio nella memoria del programma lo occupa. Per memoria del programma intendo dove vengono salvate le istruzioni del programma.

Pensaci meglio ?!?!? :grin:

Compila un programma di test come dici tu, soltanto dichiarando una variabile , e vedi in assembler cosa viene fuori!

amacbr:
Giusto, ma una dichiarazione di questo tipo P(pippo) non occupa neanche spazio nella memoria del programma, mentre se dichiaro int pippo, se pippo non e' utilizzatto non verra allocata memoria ma lo spazio nella memoria del programma lo occupa. Per memoria del programma intendo dove vengono salvate le istruzioni del programma.

Quel tipo di dichiarazione serve al compilatore per sapere quale nome simbolico hai deciso di adottare per una variabile e che dimensioni, quella variabile viene allocata nella ram ad un indirizzo specifico deciso dal compilatore se è una variabile globale oppure nello stack se è una variabile locale, in tutti e due i casi non occupa nemmeno un byte nella flash (memoria di programma).
Da notare che le variabili locali non aumentano l'uso della ram come quelle globali, però c'è il rischio di andare in stack oveflow a run time, perché vengono poste in uno spazio preallocato dal compilatore e di dimensioni prefissato, il già citato stack.
Da notare che se dichiari una variabile, sia locale che globale, che poi non viene realmente utilizzata nel programma questa non occupa spazio perché viene ignorata dal compilatore, a seconda degli ambienti di lavoro e di come è settato il warning level il compilatore può generare delle warning sia relative alle variabili non usate sia ad un eventuale pericolo di stack overflow in caso di molte funzioni annidate e/o variabili locali dichiarate "static" (non vengono distrutte all'uscita dalla funzione).

beh, facendo la prova: le dichiarazioni (sia con P() che di una variabile int), se non utilizzate, non occupano spazio nella flash. Ops :roll_eyes:
Tra l'altro ho trovato questo:http://arduino.cc/playground/Learning/Memory

Grazie della pazienza

amacbr:
beh, facendo la prova: le dichiarazioni (sia con P() che di una variabile int), se non utilizzate, non occupano spazio nella flash. Ops

Ma lo leggi quello che ti spieghiamo oppure ti diverti a farci perdere tempo ?

astrobeed:

amacbr:
beh, facendo la prova: le dichiarazioni (sia con P() che di una variabile int), se non utilizzate, non occupano spazio nella flash. Ops

Ma lo leggi quello che ti spieghiamo oppure ti diverti a farci perdere tempo ?

astrobeed, non riesco a dare un significato al tuo intervento:

niki77:

, se pippo non e' utilizzatto non verra allocata memoria ma lo spazio nella memoria del programma lo occupa. Per memoria del programma intendo dove vengono salvate le istruzioni del programma.

Pensaci meglio ?!?!? :grin:

Compila un programma di test come dici tu, soltanto dichiarando una variabile , e vedi in assembler cosa viene fuori!

come mi ha suggerito niki77 ho riprovato con degli sketch di prova, con una ventina di variabili char, poi con lo stesso numero di dichiarazioni P() e poi senza nessuna variabile, e la quantita di memoria occupata nella flash e' sempre stata uguale, al contrario di quello che ho scritto pochi post prima e come hai detto tu...
Ho riportato l'esito del test per completezza a conferma di quanto mi avete risposto.