Utilizzo puntatori

qualcuno può spiegarmi la seguente riga :

for (rdTemp & device : tempSensors)

tempSensors è un array di n elementi definiti da rdTemp

Non avendo ancora chiaro quando vanno utilizzati i puntatori, vorrei capire la "&" che scopo ha ?

Si tratta di un ciclo for "range based" che va a ciclare gli elementi di tempSensors passando i valori al blocco di codice successivo per riferimento.

Riporto qualche elemento in più per maggior chiarezza:

#define NUM_DEVICE 3
RdTemp tempSensors[NUM_DEVICE];
....

 for (RdTemp & device : tempSensors)
    {
      if (readTempByStructPointer(device)) {
        outputTemp(device.busIndex);
      }
      else {
        Serial.printf("Il dispositivo %d non ha risposto correttamente\n", device.busIndex);
      }
    }

Per ogni iterazione del ciclo for viene creato un riferimento ad uno degli elementi di tempSensors a cui viene assegnato il nome device.

Nel blocco di codice successivo, quando scrivo device è esattamente come se accedessi direttamente all'elemento i di tempSensors solo che non devo tenere conto dell'indice perché ci pensa il compilatore.

device <==> tempSensors[i]

grazie per l'intervento.
il ciclo for l'ho chiaro (questa è la parte di codice interessata )

  for (rdTemp & device : tempSensors)
      {
          sensors.getAddress(deviceId, i);      
          float temperatureC  = sensors.getTempCByIndex(i);
          device.sndMac       =  temperatureC == -127.00 ? "": 
          decodMac(deviceId);
          device.temp         =  temperatureC ;          
          i++ ;
      }   

quello che non ho capito è se "&" fa riferimento all'uso dei puntatori.
Ripeto non ho chiaro quando vanno utilizzati e se servono allo scopo di ridurre lo spazio di memoria utilizzato o ci sono aree raggiungibili solo attraverso loro.

Sto leggendo di tutto, ma credo che il criceto sia un po' in affanno

Per capire a fondo l'uso dei puntatori e degli operatori ad essi legati * e &, tutto quel materiale che vedo in foto ahimè temo che ti sarà poco utile. Non riesco a leggere tutti i titoli, ma sembrano tutorial recuperati online e materiale didattico destinato ai principianti che tipicamente si concentrano troppo sul codice e troppo poco sullo spiegare le architetture ed il funzionamento di CPU e MCU.

Quando vedi l'operatore &var nella tua mente devi leggere "l'indirizzo (di memoria) dove risiede la variabile var"

Se nel tuo codice ometti l'operatore & vai a creare una nuova variabile locale di tipo rdTemp in cui viene copiato il valore dell'array duplicandone inutilmente il contenuto. Devi valutare tu quando è il caso di usare i puntatori/passaggi per riferimento e quando no.

In questo caso, siccome nel tuo ciclo hai bisogno dei valori memorizzati nell'array puoi "puntare" direttamente alla porzione di memoria dove questi dati sono memorizzati.

Infine una considerazione personale... siccome nel tuo for loop hai bisogno dell'indice, in questo caso secondo me sarebbe stato più adeguato un ciclo for "classico".

No, lo ampersand non è un indirizzo e non si stanno usando puntatori

E cpp non c semplice

& vale come riferimento a

Ovvero un'altro nome per la stessa variabile

Non crea un nuovo oggetto ma solo un nuovo nome per un oggette preesistente

Poi è dentro a un for scritto in cpp a che lui

Ranged base for

Che permette di ciclare un array con facilità

Un piccolo esempio che mostra quello di cui parlavo prima:

Perdona, ho letto bene solo adesso

Se ti riferisci ai puntatori e non al riferimento la tua domanda assume un differente significato

I puntatori si usano sia per ridurre l'uso di memoria in c
E in cpp si preferisce invece il reference

Sia per avere accesso ad aree di memoria altrimenti non accessibili (aree allocate senza un nome con alloc() o calloc() in c)

Guardacaso ne scrivevo nei giorni scorsi

Nella mia discussione "la pappa è fatta"

Trovi alcuni esempi sia di range base for che sue alternative

E dopo vedi l'uso di puntatori per accesso ad un'area di memoria altrimenti inaccessibile

In fondo alla discussione

PS
Io, specialmente la in quella discussione, ma in generale cerco spesso di spiegare quello che faccio, per favorire l'apprendimento se fosse necessario

Grazie pe la collaborazione.

Al centro campeggia un libro che ho quasi terminato di leggere, ma l'ho trovato molto superficiale rispetto al materiale stampato da internet.
se avete testi da consigliare ben venga.

sarebbe stato più adeguato un ciclo for "classico".

in php uso molto :

foreach(array as index => data)
{
....
}

mi viene restituito sia l'indice che l'elemento.
non ho trovato nulla di corrispondente.

con questo hai colmato la mia lacuna sui cicli "FOR"

  for (CustomData_t elem : dati)
  {
// si può ricavare anche l'indice ??
  }

Ringrazio anche te per la collaborazione.

Ho trovato difficoltà nell'utilizzo degli interrupt software, su cui non trovo molta documentazione.
Per questo chiedevo se il riferimento alla memoria "&" fosse indispensabile in alcuni contesti.

No, ma ad esempio potresti aggiungere una proprietà index alla tua struct e quando vai a popolare l'array aggiorni il valore corrispondente come ho fatto nell'esempio del resto.

Giusto, adesso correggo, una distrazione
però fa piacere sapere che almeno qualcuno mi legge

ora ti leggo anch'io

non capisco il nesso tra interrupt e puntatori...

Grazie

per rispondere alla tua domanda, non si può ricavare l'indice
la' ho mostrato un'alternativa

Guru Meditation Error: Core 1 panic'ed (LoadProhibited). Exception was unhandled.

Core 1 register dump:
PC : 0x40083f5c PS : 0x00050d31 A0 : 0x800d20c7 A1 : 0x3ffbf8ec
A2 : 0x00000040 A3 : 0x00018040 A4 : 0x000637ff A5 : 0x3ffbf8cc
A6 : 0x00000000 A7 : 0xb33fffff A8 : 0x800d4610 A9 : 0x4008aac2
A10 : 0x00000000 A11 : 0x7da15afe A12 : 0x800838d8 A13 : 0x3ffbf8ac
A14 : 0x3ffc1fe8 A15 : 0x400854e4 SAR : 0x00000019 EXCCAUSE: 0x0000001c
EXCVADDR: 0x800d20d3 LBEG : 0x400866b5 LEND : 0x400866c5 LCOUNT : 0xffffffff

Backtrace: 0x40083f59:0x3ffbf8ec |<-CORRUPTED

inizialmente per il controllo periodico delle sonde ho utilizzato gli interrupts,
(poi abbandonati), ma funzionava solo il primo ciclo al secondo si presentava il messaggio allegato.

Sicuramente vi erano più problemi, ma mi è stato anche spiegato e ho trovato riscontro anche nelle piccole dispense che ho stampato, che la memoria utilizzata dagli interrupt è diversa da quella normalmente utilizzata e che andava trattata con i puntatori.
Discorso per il momento tralasciato, ma che ho intenzione di riprendere al più presto.

ah...
grazie

Si, su piattaforma ESP, la gestione degli interrupts è più complessa che su altre piattaforme ed effettivamente richiede di conoscere come è fatta la memoria e dove metterli ...

ESP-IDF distingue tra bus di memoria di istruzione (IRAM, IROM, RTC FAST memory) e bus di memoria dati (DRAM, DROM). La memoria di istruzione è eseguibile e può essere letta o scritta solo tramite parole allineate a 4 byte. La memoria dati non è eseguibile e può essere accessibile tramite singole operazioni di byte.
(Vd. ESP32 Technical Reference Manual > System and Memory)

Su ESP32, normalmente, gli interrupts si mettono in IRAM con l'apposito attributo:

void IRAM_ATTR sample_interrupt()

(Vd. IRAM-Safe Interrupt Handlers).

Ma avrai tempo più avanti per provare queste cose su ESP32 :wink:

Guglielmo

P.S.: Aggiungo inoltre che, anche se non lo vedi, su ESP32 stai girando sotto FreeRTOS™ e che quindi il loop() è in realtà all'interno di un task ... il FreeRTOS.config del ESP32 è fisso e non può essere modificato ed impone alcuni vincoli anche a livello interrupts.

1 Like

argomento da approfondire, ma credo sia presto.