Newsgroup: it.comp.lang.c
Titolo: Mescolare Little e Bid Endian

Su un'architettura Little Endian (embedded) devo leggere, in 
continuazione, delle informazioni da un dispositivo esterno (per inciso, 
la comunicazione è seriale).
Il dispositivo esterno ha già un suo protocollo (che non posso cambiare) 
che impacchetta i dati numerici in Big Endian, allineati in modo qualsiasi.
Per esempio, ad una domanda di richiesta dati, potrebbe rispondere con 
un array di 6 byte dove:
- byte 1: bitmask di flags vari
- byte 2-3: intero senza segno 0-65535 (Big Endian)
- byte 4-5-6: intero con segno 24 bit (Big Endian)
Questi dati sono numerosi (grosso modo ci sono una trentina di richieste 
dati con altrettante risposte di lunghezza media di 5 byte).
Normalmente ciclo su tutte le richieste dati in continuazione per avere 
in memoria sempre dati freschi.
Cosa me ne faccio di questi dati? Mi servono per tre cose:
- visualizzare a display se servono (cioè se l'utente entra
   in particolari schermate)
- controllare alcuni bit per verificare eventuali allarmi
   sopraggiunti da segnalare all'utente
- spedire questi dati ad un controllo esterno via Ethernet
E' chiaro che, oltre ai dati provenienti dal dispositivo esterno, ci 
sono dati "interni" che saranno in Little Endian e organizzati come voglio.
Non so cosa fare per gestire i dati del dispositivo esterno e cioè se:
- riorganizzarli subito in tipi predefiniti (all'interno di una
   struct) ad ogni ricezione dei dati
- tenermeli in memoria come array di char e, alla bisogna, convertire
   i vari dati
Nel primo caso, sarei sicuro di avere sempre i dati allineati e 
nell'ordine corretto e potrei fare le comuni operazioni (numeriche, di 
confronto...) senza problemi.
Di contro farei sempre queste conversioni anche quando non mi serve fare 
operazioni sui dati (l'utente non è sempre davanti alla macchina e non 
chiede sempre i dati su Ethernet).
Nel secondo caso, la comunicazione con il dispositivo esterno è più 
veloce (niente conversioni), ma ogni volta che devo utilizzare un dato 
(per visualizzarlo, ...) devo prima eventualmente convertirlo in un tipo 
predefinito in Little Endian.
Suggerimenti?

 i vari dati
Io convertirei subito alla ricezione del dato (ed eventualmente 
all'invio del dato). Se non altro dovresti avere un unico punto del 
codice dove converti, e da li' in poi avresti tutti i dati consistenti, 
per poter quindi fare subito tutte le operazioni/confronti che ti 
servono. Non da meno, così facendo, non rischi di impazzire a mantenere 
il codice. (ad es. ricordarti quando devi convertire e quando no, 
ridovere convertire a dovere se devi aggiungere una nuova schermata etc).
La conversione inoltre non dovrebbe essere affatto penalizzante (saranno 
30 messaggi ma 5 byte di media sono sempre 5 byte, di cui il primo, 
almeno nell'esempio che porti, non ha bisogno di conversione).
L'unica, non hai specificato se quando mandi su ethernet (verso 
controllo esterno) devi spedire big o little. Anche se in questo caso 
dovessi spedire big, io preferirei comunque lavorare nell'endianity 
nativa della scheda, e convertire solo appena prima dell' invio su network.
Ciao ( auguri a tutti ),
Gio

 nativa della scheda, e convertire solo appena prima dell' invio su network.
Su Ethernet sono completamente autonomo perchè dall'altra parte c'è un 
mio software che posso scrivere come voglio. E si tratta di software su 
PC, quindi non mi spaventa nulla... :-)

 nella conversione continua piuttosto che "alla bisogna".
L'operazione dovrebbe essere molto veloce (che scheda hai per curiosità 
?) per i short e gli int uno swap dei byte dovrebbe bastarti, (o 
chiamata a ntohs/ntohs) per i 3 byte, al limite ti tocca vedere il segno 
e prenderti cura del complemento a due mentre espandi su un int32 ma 
anche qui dovrebbe essere immediato. A meno che non ti arrivino sulla 
seriale dati a profusione (ma sarai sui 9600baud, mal che vada a 24K) 
non dovrebbe darti nessun problema.
-gio

 non dovrebbe darti nessun problema.
In realtà sono a 57600bps.

 continuazione.
Se devi fare elaborazione dei dati ricevuti è sicuramente più 
efficiente farli nel modo più consono al controllore.
Basta leggerli dalla seriale con ntohs/ntohl (come ti hanno suggerito) 
e quindi elaborarli in L.E, se questo è il modo di lavorare del 
controllore.
Ciao
Giovanni
-- 
   A computer is like an air conditioner,
   it stops working when you open Windows.
   < 
http://giovanni.homelinux.net/
 >

> Suggerimenti?
Se non devi fare elaborazioni numeriche ma solo
visualizzazioni e test di bit tienili come sono.
Per i test di bit puoi definire delle maschere
opportune con delle define.
Poi su PC hai tutte le risorse per fare quello che
vuoi.
A.


Il mondo ï¿œ bello perchï¿œ ï¿œ vario... :-)
Tirerï¿œ una monetina.


Dico anch'io la mia.
Il fatto che tu stia scrivendo codice per un controllore che lavora in
LE che legge i dati in BE non dovrebbe darti alcun problema nel caso
uno dei due cambiasse endianess (es.passi ad un controllore BE, o
cambi protocollo di comunicazione): metti una "barriera" di macro di
conversione all'entrata e all'uscita di ogni dato (come già hanno
suggerito sullo stile to ntohs). In questo modo con due define e
l'aiuto del compilatore il codice rimane indipendente da questo
dettaglio banale. ;-)
Per le performances, tieni conto che tra endianess uguali non
verrebbero effettuate conversioni, nel caso opposto un paio di shift,
quindi un tempo ridicolo rispetto alle attese della seriale o del
display.
Ciao!