Accesso a Struct come fosse array di byte

>fratt ... ti dico solo, le stringhe di caratteri usale nel modo classico, con le parentesi quadre e lascia stare questi giochini che ... è facilissimo fare cavolate e andare a scrivere sopra a quello su cui NON si doveva scrivere. Dai retta ... tanto l'ottimizzazione è a carico del compilatore che la sempre meglio di quello che tu fai a mano :smiley: :smiley: :smiley:

Guglielmo

Facevo sempre riferimento alla struttura iniziale, non mi servono le stringhe.
Trasmetto la struttura un byte alla volta con la write e dall'altra parte la leggo con la read, però poi devo mettere i dati ricevuti "dentro" la struttura gemella che ho sul ricevitore.
Quindi mi servirebbe un modo per usare la struttura come fosse un array anche in assegnazione.

fratt:
Visto che siete tutti qua ne approfitto...

Serial.write( *(p++) );

Questo vale anche al contrario? Cioè in fase di assegnazione?
Tipo

*(p++) = Serial.read();

Qui non ho un pc con l'ide installato per fare delle prove.

Si, anche al contrario. Mettiti nei panni del compilatore.
Una byte x; non ha ambiguità, può solo contenere un valore intero.
Ma byte *p; p contiene un valore indirizzo, ma con *p accedi al valore a cui punta p
Quindi p=qualcosa carichi indirizzo *p=qualcosa carichi un valore a dove punta p *(p+1)=carichi qualcosa a indirizzo +1

Ottimo grazie

Per la questione metodi write; volevo solo dire che ho fatto una prova su Uno.

void setup() 
{ uint8_t vet[]={65,66,67,68,0,69};
  Serial.begin(9600);
  // Serial.write(vet);   // errore di compilazione
  Serial.write( (const char*)vet );   // ABCD stringa
  Serial.write("\n");                // stringa costante
  Serial.write(vet,6);              // ABCDE  array di byte
  Serial.write("\n");
}

La write rispetto ad un array lo stampa con la sintassi write(array,lun)
Poi ha il metodo const char * che serve per le costanti tipo la write("\n") che ho scritto sopra
Se si vuole "forzare" l'array di char (stringa) bisogna fare un cast, il solo array passato, da errore di compilazione (giustamente direi)
Il mio dubbio era che accettasse la write(vet), cosa che non fa

@fratt, occhio quindi coi puntatori anche a verificare cosa si aspetta come parametro una funzione.
Dato l'assegnazione: unsigned char *p=(unsigned char *)&trasmissione.dati ;
Serial.write(p+ i); ti stampa i byte che formano indirizzo contenuto in p (come detto da @Mauro)
Serial.write( *(p+i) ); forma corretta
mentre questa
Serial.write(p+ i, 1 ); ti stampa ciò a cui punta p+i

Sì certo, mi controllo la libreria.
Grazie

ti dico solo, le stringhe di caratteri usale nel modo classico, con le parentesi quadre e lascia stare questi giochini

Si, ma anche con un puntatore a tipo non void puoi usare la sintassi degli array cioè ptrTo[indice] sia a destra che a sinistra dell'assegnazione.

Riguardo a "giochini" non sono dello stesso avviso, nel senso che se devi fare qualcosa e non hai esperienza con la sintassi dei puntatori usa [] e vai sul sicuro, mentre se stai studiando e sperimenti con le sintassi per giorni e giorni prendi confidenza con le sintassi più complesse e allora usale sempre e più le usi più ti appariranno chiare.

La differenza tra "concetto di puntatore" e la "sintassi e aritmetica dei puntatori" è ampia, certo prima bisogna avere chiaro il concetto, poi viene il resto e ti scontri con ++ptrTo e ptrTo++ e con tutto ciò che c'è attorno ai puntatori al casting esplicito implicito ecc.

Ad esempio la semplice e comprensibile sintassi seguente:

char* str = "ABC";

diventa meno comprensibile come segue:

const char* const str = "ABC";

Puntatore costante punta a dato costante; non posso modificare ne il puntatore str ne "ABC".
vedi link

Occhio alla differenza di casting tra C e C++. Quella mostrata qui e la sintassi standard C, C++ diventerà meno tollerante.

Ciao.

Grazie, anche se comincia a girarmi la testa...
La storia della sintassi tipo array con i puntatori non la sapevo, dopo cena faccio qualche prova

ok, eccomi cari signori

adesso ho tutto lo spazio che serve

quindi come promesso parliamo della differenza tra i due frammenti incriminati di programma

facendo l'esempio di array di char e di puntatori a char

char array[]="ma che bel castello";

e

char * puntatore = "ma che bel castello";

il primo alloca memoria per un array di 20, crea un oggetto array conosciuto dal compilatore, lo inizializza prendendo i dati da una costante simbolica e permette la modifica del contenuto dell'array (non della sua dimensione)
sono legali e lavorano come ci si aspetta cose come

sizeof array;
// notare senza parentesi, non è mica una funzione
// che correttamente riporta 20
array[1]='i';
// che correttamente trasforma la stringa in "mi che bel castello"

sono illegali e/o non funzionano cose come;

array=&"altra stringa";
// che tenta di cambiare l'indirizzo ASSOCIATO al nome dell'array e non, come si potrebbe pensare l'indirizzo CONTENUTO nel puntatore

la seconda forma invece alloca memoria solo per un puntatore, e "casualmente" in questo caso, lo inizializza ad una "costante simbolica"
in effetti sarebbe possibile anche:

char * puntatore;

che crea il puntatore, ma non lo inizializza ne alloca la costante simbolica, il puntatore esisterebbe comunque,
NULL, ma ci sarebbe

ora, lo standard non è chiaro su come vengono conservate le costanti simboliche, sembra che con Arduino siano comunque in RAM, anche se in generale non è garantito, e K&R dicono che non dovrebbe andare in memoria modificabile
quindi cose come queste NON vanno, o se vanno si comportano come non ci si aspetta

sizeof puntatore;
// restituisce 2, indipendentemente da quanto è lunga la stringa, e per qualunque tipo dati si usi
puntatore= & "un'altra stringa";
//che in effetti alloca una seconda costante simbolica e ne scrive l'indirizzo nel puntatore, anche se uno penserebbe che "cambia" la stringa puntata
// letteralmente è così: fa si che il puntatore punti a una stringa differente, in un'altra posizione di memoria
// anche se con "cambia la stringa" di solito si intende "ne cambia il contenuto"
// anche questo:
*(puntatore+1)='i';
// non è corretto, anche se sembra che con arduino vada
// cambia il secondo carattere di una costante simbolica allocata in memoria, ma abbiamo visto che non è detto che sia memoria RAM
puntatore=array;
// incredibilmente va, anche se NON copia, come a prima vista un inesperto potrebbe credere
// dicevo: NON copia il contenuto dell'array, ma cambia il contenuto del puntatore per farlo puntare al primo carattere dell'array di caratteri
// di contro questo non va:
array=puntatore;

per semplificare diciamo che

char array[]="stringa";

equivale (non proprio, ma quasi) a:

char * const array = "stringa";

mentre

char * puntatore = "stringa";

equivale (non proprio, ma quasi) a:

const char * array = "stringa";

ma rimane il fatto che sizeof fa il suo dovere solo con gli array

tutto questo "cinema" è dovuto al fatto che "effettivamente" gli array sono alle volte gestiti come se fossero dei puntatore, ma "esistono" a parte
mentre un puntatore ha significato solo per aree di memoria effettivamente inizializzate

Maurotec:
Ad esempio la semplice e comprensibile sintassi seguente:

char* str = "ABC";

semplice, comprensibile ma in generale erronea mi correggo: possibile fonte di errori

le costanti simboliche sono e dovrebbero rimanere appunto "costanti"

Ringrazio Standardoil per l'esauriente spiegazione che però probabilmente digerirò solo fra qualche mese.
E ringrazio tutti gli altri per non aver obbligato Standardoil a consolare una neo-vedova.

Se permettete chiederei un'ultima conferma.
Ho provato a mettere a frutto quello che mi avete spiegato.
Prendiamo questo spezzone di codice:

t_pack trasmissione, ricezione;
unsigned char *t, *r;

  trasmissione.dati.idmsg = 12345678;
  trasmissione.dati.iddest = 254;
  trasmissione.dati.durata = 987654321;
  trasmissione.crc = calc_crc32((unsigned char *)&trasmissione.dati,DIMDATI);

  t = (unsigned char *)&trasmissione;
  r = (unsigned char *)&ricezione;
  for (byte i=0; i < DIMPACK; i++) {
    r[i] = t[i];
    //*(r++) = *(t++);
  }

  Serial.println();
  Serial.println();
  Serial.println("trasmissione");
  Serial.println(trasmissione.dati.idmsg);
  Serial.println(trasmissione.dati.iddest);
  Serial.println(trasmissione.dati.durata);
  Serial.println(trasmissione.crc);
  Serial.println();
  Serial.println("ricezione");
  Serial.println(ricezione.dati.idmsg);
  Serial.println(ricezione.dati.iddest);
  Serial.println(ricezione.dati.durata);
  Serial.println(ricezione.crc);

Sulla seriale vedo gli stessi valori sia per trasmissione che per ricezione, con entrambe le righe dentro il for.
Quindi la copia byte/byte da una struttura all'altra funziona.
Le 2 sintassi dentro il for (quella con [] e quella con *) sono entrambe formalmente corrette o una delle 2 funziona per culo?

vuoi dire:

    r[i] = t[i];
    //*(r++) = *(t++);

no, funzionano e sono corrette

diciamo che la seconda si usa quando vuoi "ricordare" che stai usando puntatori, ma alla fine sono equivalenti, in quel for

Sì, intendevo quelle 2 righe.
Grazie della conferma.

Ringrazio nuovamente tutti quelli che sono intervenuti in questa discussione. Ho capito più cose sui puntatori qua che in 6 mesi di università...

Sono corrette.
Per essere "identiche" la seconda dovrebbe essere (r+i) =(t+i) ;

Grazie

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.