@lock
Anche in asm puoi usare una cella di memoria al cui interno ci scrivi un indirizzo di memoria, che equivale a creare puntatori, ma in quel caso ricavi il contenuto della prima cella e lo usi per accedere alla cella di memoria che risiede a quell'indirizzo. Quindi non credo che si tratti di C, C++ o pascal o modula ecc, semplicemente la ram è fatta così. Ma poi che mi fai scrivere che lo sai meglio di me

Rimango 'ingannato' dal fatto che l'esito sembra lo stesso, ma sicuramente c'è un motivo perché si usa uno o l'altro modo.
Nella tua testa c'è una grande confusione, che diminuirà solo dopo che sperimenti in prima persona come funzionano il C/C++, e l'unico modo è quello di usare un compilatore per PC o (IDE). Crei alcune variabili e stampi i loro indirizzo, crei funzioni e passi i parametri in tutti i modi conosciuti, nessuna variante esclusa. Sperimentare con il C/C++ su un dispositivo embedded non è pratico nè comodo, se ti convinci di ciò ti renderai conto come stanno le cose e alla fine considererai anche banale l'argomento che comunque non mancherà di fregarti quando meno te lo aspetti.
readBytes prende un puntatore ad tipo unsigned char, quindi il puntatore sarà grande 16 bit ma la cella a cui punta è grande 8 bit. Nella chiamata puoi passare un puntatore o un array (vedi cosa dice lesto).
Nel caso specifico di readBytes la funzione è pensata per gestire l'array passatogli attraverso il puntatore "values", infatti il parametro seguente si chiama length, cioè lunghezza di che ? dell'array.
readUInt prende due argomenti, il primo passato per valore e il secondo passato per riferimento.
Se vuoi puoi scrivere dei pezzi di programma piccoli a cui aggiungi i commenti (chiari chiari) che poi noi qui li correggiamo.
char *charPtr; // Un puntatore non ha segno quindi unsigned char al posto di char, ma non è un obbligo
charPtr prende 2 celle di memoria in quanto il puntatore in AVR è grande 16 bit.
Il dato a cui punta invece è grande 8 bit (lo specifica char).
Per ricavare il dato (valore) a cui punta charPtr si antepone *, es: char myChar = *charPtr; // ricavo il valore e lo salvo in myChar, il valore può avere segno negativo o positivo.
charPtr++; incrementa il puntatore di 1 cella, questo mi da accesso alla cella seguente charPtr.
*(charPtr++) incremento e ricavo il valore.
Sono un poco maligno perché voglio che ti convinci a sperimentare il C/C++ su un pc, sarò ancora più maligno
(se prima non lo fa lesto) la prossima volta con i puntatori a puntatori (che mi procurano mal di testa).
Ciao.