Ciao ragazzi, sto cercando di imparare un po' di C un pelino più avanzato, stavo vedendo i puntatori.
I puntatori puntano l'indirizzo di una variabile, da quello che ho capito se devo puntare un intero, un long o un double sempre un byte viene riservato in memoria, cioè il numero intero dell'indirizzo del dato in memoria.Ma dov'è questa memoria? per esempio se nello stesso identico codice invece di usare un intero, uso un puntatore quando compilo, la lunghezza dello sketch è di circa 24 bytes in più quando dovrebbe essere uguale al precedente, oppure una serie di if annidate producono un codice di x byte, lo stesso risultato usando case produce un codice più lungo, tutte e due le strutture più corto della serie di if, insomma senza pretendere la spiegazione dei casi specifici, come faccio a sapere quanto uso di memoria fa un istruzione piuttosto di un altra, i cicli di clock che impiega e dove fisicamente viene allocato un dato con #define, PROGMEM, o malloc() ???
tanti dubbi ragazzi, ciao!
Francesco_MIRM:
... Ma dov'è questa memoria? per esempio se nello stesso identico codice invece di usare un intero, uso un puntatore quando compilo, la lunghezza dello sketch è di circa 24 bytes in più quando dovrebbe essere uguale al precedente, oppure una serie di if annidate producono un codice di x byte, lo stesso risultato usando case produce un codice più lungo, tutte e due le strutture più corto della serie di if, insomma senza pretendere la spiegazione dei casi specifici, come faccio a sapere quanto uso di memoria fa un istruzione piuttosto di un altra, i cicli di clock che impiega e dove fisicamente viene allocato un dato con #define, PROGMEM, o malloc() ???
tanti dubbi ragazzi, ciao!
Le variabili vengono memorizzate nella RAM del ATmega;
I puntatori sono interi.
Il #define non consuma memoria; nella compilazione viene sostituito la variabile col numero numerico.
Nei maggior parte dei casi non é importante sapere quanto consuma una funzione o un altra.
Perché hai bisogno di saperlo?
Ciao Uwe
Completo le info specificando che con #define ottieni lo stesso consumo di memoria che avresti usando un dato di tipo "const" perché il compilatore sostituisce appunto i numeri reali durante la compilazione. Se vuoi sapere il consumo di memoria di un tuo sketch puoi usare avr-size (cerca sul forum per la sintassi).
PROGMEM permette di accedere ad una variabile direttamente dalla memoria Flash senza doverla copiare nella SRAM dove "vivono" le variabili del programma.
Malloc() è un costrutto che sarebbe bene non usare a cuor leggero su un micro ad 8 bit con limitati quantitativi di memoria come un Atmega328.
Teoricamente serve per liberare lo spazio utilizzato da una variabile una volta che questa non è più usata ma se usato indiscriminatamente potrebbe portare alla frammentazione della RAM con la conseguenza di far peggio che meglio.
Appunto se i puntatori sono interi, se al posto di int _addr; uso int *_addr, il codice compilato dovrebbe essere dello stesso numero di bytes.
Come faccio a sapere quanta RAM è occupata?
Per quanto riguarda sapere quanto consuma una funzione, sto cercando di capire come funziona la memoria e l'allocazione dei tipi di dato, vedere due sketch che fanno la stessa cosa avere 150-200 bytes di differenza mi manda in pappa il cervello, vorrei capire il modo migliore per gestire le variabili, strutture dati, e quali strutture di controllo preferire, più che altro a scopo didattico-hobbystico, eheheh
Francesco_MIRM:
Appunto se i puntatori sono interi, se al posto di int _addr; uso int *_addr, il codice compilato dovrebbe essere dello stesso numero di bytes.
No, hai una variable in piú e dopo la compilazione un codice di macchina diverso.
Francesco_MIRM:
Come faccio a sapere quanta RAM è occupata?
come scrive Leo con avr-size
Francesco_MIRM:
Per quanto riguarda sapere quanto consuma una funzione, sto cercando di capire come funziona la memoria e l'allocazione dei tipi di dato, vedere due sketch che fanno la stessa cosa avere 150-200 bytes di differenza mi manda in pappa il cervello, vorrei capire il modo migliore per gestire le variabili, strutture dati, e quali strutture di controllo preferire, più che altro a scopo didattico-hobbystico, eheheh
Se lo vuoi sapere solo per scopi didattici-hobbystici Ti dico lascia stare; é troppo impegnativo per saperlo.
Ciao Uwe
Ecco! per sapere queste cose dove posso guardare? un altra cosa che voglio capire è quella delle varie strutture di controllo, quale preferire? è una questione di annidamento? Suddividere un programma in più procedure e funzioni aumenta la sua grandezza? grazie uwe e leo, figuratevi che non c'è qualcosa che posso leggere sull'argomento specifico?
uwefed:
Francesco_MIRM:
Appunto se i puntatori sono interi, se al posto di int _addr; uso int *_addr, il codice compilato dovrebbe essere dello stesso numero di bytes.No, hai una variable in piú e dopo la compilazione un codice di macchina diverso.
Francesco_MIRM:
Come faccio a sapere quanta RAM è occupata?come scrive Leo con avr-size
Francesco_MIRM:
Per quanto riguarda sapere quanto consuma una funzione, sto cercando di capire come funziona la memoria e l'allocazione dei tipi di dato, vedere due sketch che fanno la stessa cosa avere 150-200 bytes di differenza mi manda in pappa il cervello, vorrei capire il modo migliore per gestire le variabili, strutture dati, e quali strutture di controllo preferire, più che altro a scopo didattico-hobbystico, ehehehSe lo vuoi sapere solo per scopi didattici-hobbystici Ti dico lascia stare; é troppo impegnativo per saperlo.
Ciao Uwe
per essere didattico-hobbystico ho studiando parecchio, non è che sto proprio a 0, quello che voglio fare lo faccio, solo che voglio capire perchè lo faccio, invece di scrivere lo stesso codice e libreria 10 volte e fare varie prove, vorrei saperlo prima, se sapevo prima che usando un puntatore mi trovavo due variabili non modificavo per niente, lo so che è difficile..
Alcune risposte alle tue domande le trovi all'interno dei sorgenti del compilatore GCC. Se usi un sistema operativo GNU/Linux, dovresti avere la possibilità di installare un pacchetto avr-gcc-docs, nel mio caso il pacchetto non esiste, e quindi ho compilato avr-gcc da sorgenti abilitando la compilazione di tutta la documentazione anche in pdf.
In alternativa puoi provare a navigare il sito Redirect Notice al fine di trovare la documentazione a cui mi riferisco consultabile in html.
Nota che alcune delle tue domande trovano risposte differenti passando da un compilatore ad un altro e da una architettura all'altra. Es ci sono alcune architetture dove un intero è grande 32bit.
Appunto se i puntatori sono interi, se al posto di int _addr; uso int *_addr, il codice compilato dovrebbe essere dello stesso numero di bytes.
C'è da notare una cosa importante: int *ptr_int è un puntatore ad un'intero, e non è un puntatore ad una variabile intera. Al momento della dichiarazione non c'è allocazione di memoria e ptr_int punta ad un'indirizzo di memoria casuale. I puntatori è bene azzerarli. Per assegnare un valore al puntatore ptr_int devi avere una variabile intera già allocata nello stack, allora puoi prelevare l'indirizzo di questa e salvarlo in ptr_int.
int an_int = 0;
int *ptr_an_int = &an_int;
I puntatori sono comodi perchè te li puoi portare a spasso per i vari file, nelle funzioni e oggetti senza per questo costringere il compilatore a creare una copia locale della variabile, però così modifichi l'oggetto/varibile puntato dal puntatore.
Se un puntatore è già stato correttamente inizializato puoi prelevare il valore che contiente quell'indirizzo di memoria anteponendo l'operatore di dereferenziazione "*".
int val = *ptr_an_int;
val ora contiene il dato memorizzato all'indirizzo ptr_an_int.
Se sei determinato devi allora approfondire la conoscenza del linguaggio C/C++, scoprirai allora cosa c'è dietro le quinte di qualunque IDE, Arduino IDE compreso.
Altra cosa il case switch viene trasformato in asm allo stesso modo di come viene trasformato un if ... else if .... else if...., quindi il case va usato quando il codice che scrivi è più leggibile, sai tanti if annidati sono un'inferno da leggere, ancora peggio se sono lunghi.
Per sapere quanti cicli cpu consuma una struttura condizionale o qualunque altro codice devi conoscere il linguaggio asm. Impostando il compilatore avr-gcc in modo da generare dei file .s .ii ecc. puoi guardare cosa fa il preprocessore c/c++ ed il compilatore c/c++. In special modo gcc trasforma qualunque linguaggio ad esso compatibile, in liguaggio assembly. Questo è un vantaggio perchè c'è anche il modo di usare un'altro assemblatore asm al posto di "as" che è l'assemblatore di default.
Ciao.
Il compilatore introduce delle ottimizzazioni al codice e lavora anche in base a come gli si "presenta" il codice: il risultato sono spesso binari differenti. Se vuoi un codice di una dimensione quasi fissa l'alternativa che mi viene in mente è usare l'assembly: lì il compilatore ha meno libertà d'azione.
per essere didattico-hobbystico ho studiando parecchio, non è che sto proprio a 0, quello che voglio fare lo faccio, solo che voglio capire perchè lo faccio, invece di scrivere lo stesso codice e libreria 10 volte e fare varie prove, vorrei saperlo prima, se sapevo prima che usando un puntatore mi trovavo due variabili non modificavo per niente, lo so che è difficile..
Concordo.
Cioè magari modificavi, ma con cognizione di causa, invece che per sentito dire. In realta non si sa se ti ritrovi con due variabili, questo è il compilatore che lo decide. Sembra logico che se una varibile contiente un indirizzo e questo non cambia durante tutto il codice, il compilatore dovrebbe scrivere direttamente l'indirizzo e fare fuori la varibile dallo stack. Questo di sicuro accade con i puntatori const dove l'indirizzo è una costante ed il valore contenuto a quell'indirizzo non lo è.
E tutto molto complesso e l'unica modo di fare luce è studiare asm ed i file generati dal processo di compilazione per vedere cosa succede. Ovviamente non puoi usare Arduino IDE a tal scopo, ma un IDE generico. Inoltre occorre anche conoscere tutti i flag che il preprocessore/compilatore/assemblatore/linker mettono a disposizione per modificare il loro comportamento. Credimi è un'inferno, dopo anni rimane sempre un'inferno ma con l'aria condizionata.
Ciao.
Castellammare di Stabia, 27 Dicembre 2011
Ti invito a consultare il manuale sui puntatori all'indirizzo
thpitagora.altervista.org/puntatori.pdf
Il file pdf potrebe esserti utile
Cordiali saluti,
Francesco