Cos'è ElectroYou | Login Iscriviti

ElectroYou - la comunità dei professionisti del mondo elettrico

Uso corretto dei data type.

Progetti, interfacciamento, discussioni varie su questa piattaforma.

Moderatori: Foto UtenteMassimoB, Foto UtenteWALTERmwp, Foto Utentexyz

0
voti

[1] Uso corretto dei data type.

Messaggioda Foto Utentelucaking » 26 feb 2018, 13:36

Ciao a tutti,
tutto è cominciato con la necessità di leggere in maniera veloce, economica e occasionale una eprom M27C512.
Arduino si è rivelato comodo e veloce, ma scrivendo del codice un poco piu "evoluto" rispetto ai mie standard, ho notato alcune cose e sono cominciati a sorgermi dei dubbi. #-o #-o

Ho notato che nei vari esempi presenti nell' IDE di arduino, sia per riferirsi ai vari pin o anche per leggerne o forzarne lo stato, si usano variabili di tipo int che se ho capito bene occupano due byte, quando io credevo bastasse dichiararle come tipo byte,boolean o char occupando solo un byte.
Oppure nel caso della nomenclatura dei pin convenisse addirittura attribuire il numero del pin definendo una macro , per esempio:
Codice: Seleziona tutto
#define led 13

piuttosto che
Codice: Seleziona tutto
int led = 13;

Siccome sono certo del fatto che chi ha scritto gli esempi ha MOOOOLTA piu esperienza di programmazione di me, qualcuno può spiegarmi il perche di queste scelte?

Grazie O_/
Avatar utente
Foto Utentelucaking
898 2 5 8
Expert
Expert
 
Messaggi: 829
Iscritto il: 29 mag 2015, 14:28

0
voti

[2] Re: Uso corretto dei data type.

Messaggioda Foto Utentegvee » 26 feb 2018, 14:05

lucaking ha scritto:qualcuno può spiegarmi il perche di queste scelte?

Per il perché bisognerebbe vedere i sorgenti, che non hai linkato.

Dichiarare

Codice: Seleziona tutto
#define A 10


e

Codice: Seleziona tutto
int A = 10;


ovviamente comporta le dovute differenze in quanto all' uso (una macro ha un valore e non lo puoi cambiare, una variabile invece sì, come ben saprai), ma a livello di performance ho i miei dubbi che cambi qualcosa tra i due codici..
Se hai dubbi a riguardo puoi sempre disassemblare il codice e valutare le differenze.
Avatar utente
Foto Utentegvee
570 2 6
Frequentatore
Frequentatore
 
Messaggi: 204
Iscritto il: 11 feb 2018, 20:34

0
voti

[3] Re: Uso corretto dei data type.

Messaggioda Foto Utentealdofad » 26 feb 2018, 14:47

lucaking ha scritto:Ciao a tutti...

La tua riflessione è corretta, un int richiede proprio 2 bytes, bisogna invece adoperare l'uint8_t per riferirsi ai pin in modo economico con un solo byte.

La #define non adopera memoria dinamica, esattamente come una "static const". Personalmente preferisco "static const" se non ho necessità di farne riferimento nelle macro.

Con arduino la memoria dinamica si risparmia soprattutto in due modi:
1- Evitare l'hard coding con il Serial.println("pippo pluto") sostituendolo con PSTR. Esempio:
Codice: Seleziona tutto
void setup() {
  Serial.begin(57600);
  println(PSTR("pluto"));
}
void loop() {}

void println(PGM_P s) {
  char c;
  while ((c = pgm_read_byte(s++)) != 0)
    Serial.print(c);
  Serial.println();
}


2- Adoperare singolarmente i bit nei boolean, in questo modo puoi memorizzare 8 valori in un singolo boolean. Se ti interessa ti spiego postandoti un paio di funzioncine

Ad ogni modo per togliersi ogni dubbio basta leggere il log dopo la compilazione o dopo l'upload...

Sketch uses 1824 bytes (0%) of program storage space. Maximum is 253952 bytes.
Global variables use 188 bytes (2%) of dynamic memory, leaving 8004 bytes for local variables. Maximum is 8192 bytes.
Avatar utente
Foto Utentealdofad
843 4 5
Sostenitore
Sostenitore
 
Messaggi: 689
Iscritto il: 21 gen 2014, 1:07
Località: Treviso

2
voti

[4] Re: Uso corretto dei data type.

Messaggioda Foto Utentexyz » 26 feb 2018, 15:07

lucaking ha scritto:...
Oppure nel caso della nomenclatura dei pin convenisse addirittura attribuire il numero del pin definendo una macro , per esempio:
Codice: Seleziona tutto
#define led 13

piuttosto che
Codice: Seleziona tutto
int led = 13;

...

Gli esempi presenti nel IDE di Arduino non sono scritti bene, tra le critiche che si possono fare è appunto come vengono specificati i pin del microcontrollore utilizzati nel codice.

Il linguaggio di programmazione utilizzato dal IDE di Arduino è un sottoinsieme del C/C++, quindi valgono le regole basi di questi linguaggi.

In C di solito le costanti sono definite con delle macro, espanse poi dal preprocessore prima di avviare la vera compilazione, ad esempio (io uso la notazione delle costanti in maiuscolo):

Codice: Seleziona tutto
#define PIN_LED 13

in questo modo non viene dichiarata nessuna variabile nella memoria RAM e ogni volta che viene usata il compilatore decide quale rappresentazione interna usare o in RAM o nei registri.

L'uso di dichiarare e istanziare una variabile nella RAM in questo modo:

Codice: Seleziona tutto
int pin_led = 13;

non si tratta di nessuna costante (il nome non è maiuscolo) ma viene per forza utilizzata la RAM per memorizzarla e viene anche dichiarata pubblica quindi non eliminata se non utilizzata dal compilatore.

Se si aggiunge la keyword "const":

Codice: Seleziona tutto
const int PIN_LED = 13;

adesso è una costante, il compilatore la utilizzerà come una costante ma verrà comunque istanziata in RAM perché è dichiarata pubblica.

Se si aggiunge la keyword "static":

Codice: Seleziona tutto
static const int PIN_LED = 13;

è sempre una costante, ma è stata dichiarata privata. Se il compilatore non la utilizzerà come una variabile in memoria RAM non verrà istanziata con risparmio di memoria.

Esiste un altro modo per dichiarare una costante è utilizzare "enum" ma evito di spigarlo, si complica solo le cose e poi è usato raramente.

Come ultima cosa aggiungo che il "define" non viene specificato il tipo e ha una maggior compatibilità col C. L'uso di "static const <type>" viene specificato il tipo, quindi il compilatore ha un controllo maggiore in C++ visto che in C si hanno delle limitazioni ad usarlo.
Avatar utente
Foto Utentexyz
5.930 2 4 5
G.Master EY
G.Master EY
 
Messaggi: 1574
Iscritto il: 5 dic 2009, 18:37
Località: Italy Turin

0
voti

[5] Re: Uso corretto dei data type.

Messaggioda ucr » 26 feb 2018, 15:09

Gli standard embedded, tra cui il MISRA/C, richiedono che le costanti vengano dichiarate con il qualificate const (es. const uint8_t n = 10;). Inoltre è previsto dal MISRA/C che vengano usati i tipi di variabili che indicano la dimensione occupata:

"Rule 6.3 (advisory): typedefs that indicate size and signedness should be used in place of the basic numerical types."


Chiaramente parlare di standard quando si usa Arduino non ha molto senso, però prendere spunto per imparare da contesti seri è decisamente positivo.
ucr
322 2 3 5
---
 

0
voti

[6] Re: Uso corretto dei data type.

Messaggioda Foto Utentelucaking » 26 feb 2018, 16:51

xyz ha scritto:Gli esempi presenti nel IDE di Arduino non sono scritti bene.....

Bene, direi che per avvicinarmi al C sono partito nel modo giusto.... #-o

Premetto che come avrete capito l' uso che faccio di arduino e gli sketch che mi capita di scrivere vanno poco oltre il BlinkLed quindi so che le risorse dell' Atmega328 sono piu che sufficienti anche se occupo ram o registri del processore per fare cose a caso, è solo che mi piacerebbe capire cos'è giusto e cosa no.

Ringrazio tutti per le risposte, e siccome siete stati molto esaustivi per quanto riguarda l' argomento costanti e variabili, ne approfitto per esporvi l' altro mio dubbio che abbiamo già accennato.

Nel seguente esempio, 02.Digital/Button:
Codice: Seleziona tutto
// constants won't change. They're used here to
// set pin numbers:
const int buttonPin = 2;     // the number of the pushbutton pin
const int ledPin =  13;      // the number of the LED pin

int buttonState = 0;         // variable for reading the pushbutton status

void setup() {
  pinMode(ledPin, OUTPUT);     
  pinMode(buttonPin, INPUT);     
}

void loop(){
  buttonState = digitalRead(buttonPin);

  if (buttonState == HIGH) {     
    digitalWrite(ledPin, HIGH); 
  }
  else {
    digitalWrite(ledPin, LOW);
  }
}

le cose sembrerebero un po meglio per come vengono dichiarati i pin utilizzati (in questo caso se ho capito bene "static" è inutile, giuso?).

Il dubbio nasce sulla dichiarazione della variabile
Codice: Seleziona tutto
int buttonState = 0;

ho gia notato che inizializzandola come boolean piuttosto che char o byte si risparmiano 4 bytes e il compilatore non si lamenta.
Il discorso è: cos' è giusto fare?

Nel file Arduino.h, ho trovato la seguente riga:
Codice: Seleziona tutto
int digitalRead(uint_8);

Vuol dire che la funzione digitalRead ritorna un intero che occupa un byte?
Se si, perche si usa int che ne occupa 2?
Avatar utente
Foto Utentelucaking
898 2 5 8
Expert
Expert
 
Messaggi: 829
Iscritto il: 29 mag 2015, 14:28

1
voti

[7] Re: Uso corretto dei data type.

Messaggioda Foto Utenteluxinterior » 26 feb 2018, 17:08

Su architetture a 8bit può avere senso porsi il problema di come dichiarare una variabile. Un int "occupa" due byte quindi due registri (che hanno appunto dimensione 8bit) quindi sarebbe bene, dove possibile, dichiarare la variabile uint8_t o int8_t per evitare di coinvolgere un secondo registro che si traduce ogni volta i un doppio accesso alla ram. Un compilatore però ottimizza ed è in grado di riconoscere queste possibili semplificazioni, anche se tu dichiari int e il compilatore "capisce" che la variabile si mantiene in 8bit crea un codice compilato ottimizzato.
Nelle architetture ARM a 32bit non avrebbe molto senso otimizzare il datatype dichiarando int8_t o int32_t perché coinvolgono sempre un solo registro a 32bit, quindi potresti usare ovunque int32_t Anzi, poiché l'allineamento indirizzi è multiplo di 16 o 32 bit, dichiarare una varibile int8_t fa sì che il compilatore aggiunga uno o tre byte vuoti e inutilizzati per mantenere l'allineamento delle variabili, quindi la variabile uint8_t usa in realtà un int16_t o int32_t. Detto questo però c'è un altro aspetto da considerare: il corretto datatype è importante per la lettura del codice e per il debug.
Avatar utente
Foto Utenteluxinterior
2.507 2 4 8
Expert EY
Expert EY
 
Messaggi: 1472
Iscritto il: 6 gen 2016, 17:48

0
voti

[8] Re: Uso corretto dei data type.

Messaggioda Foto Utenteluxinterior » 26 feb 2018, 17:13

Dimenticavo:
Vuol dire che la funzione digitalRead ritorna un intero che occupa un byte?
Se si, perche si usa int che ne occupa 2?


In assembler le cose sono diverse
se la procedura ritorna un byte in un intero il compilatore farà: (più o meno)
mov registro, dato a 8bit
zero registro successivo per restituire un valore a 16bit

La differenza è che se restituisse un intero dovrebbe fare
mov registro, dato a 8bit basso del valore intero
mov registro, dato a 8bit alto del valore intero

quindi du eaccessi alla memoria e non uno come nel caso precedente
Ma come detto questo lo otimizza il compilatore
Avatar utente
Foto Utenteluxinterior
2.507 2 4 8
Expert EY
Expert EY
 
Messaggi: 1472
Iscritto il: 6 gen 2016, 17:48

0
voti

[9] Re: Uso corretto dei data type.

Messaggioda Foto Utentelucaking » 26 feb 2018, 17:27

Grazie, spiegate cosi le cose si che mi piacciono. :ok:

Il compilatore dell' IDE di arduino che dal log sembra essere lanciato con l' opzione -Os, usando una variabile di tipo int a fine compilazione restituisce un binario 4 bytes piu grande che utilizzando una variabile di tipo boolean.
Per il discorso lettura del codice potrebbe pure avere senso, alla fine lo stato di un pin digitale puo essere o 0 o 1 no?
Avatar utente
Foto Utentelucaking
898 2 5 8
Expert
Expert
 
Messaggi: 829
Iscritto il: 29 mag 2015, 14:28

0
voti

[10] Re: Uso corretto dei data type.

Messaggioda Foto Utentexyz » 26 feb 2018, 18:07

lucaking ha scritto:Per il discorso lettura del codice potrebbe pure avere senso, alla fine lo stato di un pin digitale puo essere o 0 o 1 no?

Le cose sono più complesse, tu stai usando API di Arduino e quel numero di pin serve solo per indicare in modo univoco un pin, poi internamente nel codice della libreria di Arduino vengono fatti una serie di confronti per individuare il registro e il pin interessato in base al microcontrollore in uso. I dettagli sono tutti spiegati nel datasheet ufficiale del microcontrollore utilizzato.

Consiglio di dichiarare le variabili costanti con "static", come ho scritto in precedenza, in questo modo:

Codice: Seleziona tutto
static const int ledPin =  13


Come le stai utilizzando il compilatore GCC per AVR dovrebbe ottimizzare il codice e non usare RAM per contenere il valore della costante ma usarla semplicemente per chiamare la funzione di libreria.
Avatar utente
Foto Utentexyz
5.930 2 4 5
G.Master EY
G.Master EY
 
Messaggi: 1574
Iscritto il: 5 dic 2009, 18:37
Località: Italy Turin

Prossimo

Torna a Arduino

Chi c’è in linea

Visitano il forum: Nessuno e 1 ospite