Newsgroup: it.comp.lang.c++
Titolo: conversione valore float da arch. BIG ENDIAN a low endian

Ciao,
qualche buon'anima sa come si possa convertire un valore float (32 bit)
salvato da un'applicazione su architettura BIG ENDIAN (es.: motorola 680xx)
per un'architettura low endian (intel) ?
Il seguente stralcio di codice funziona per un tipo long (32 bit), ma non
credo (ho provato...) che l'applicazione ad un float dia risultati corretti.
[argh! devo procurarmi informazioni sulla struttura dati float!]
// =========================================================================
// scambia tra loro le 2 word (+s,-s) della long puntata da pValue, ovvero:
// trasforma una long 32bit da BIG ENDIAN a low endian
void utils::swapL(long* pValue)
{
  long val = *pValue;
  *pValue  = (((val & 0xff000000)>>24) | ((val & 0x00ff0000)>>8) |
                        ((val & 0x0000ff00)<<8)  | ((val &
0x000000ff)<<24));
}
// =========================================================================
nell'esempio seguente, leggo 4 byte da un file IFF-LWO (di lightwave,
applicazione inizialmente sviluppata su Amiga) che contiene la lunghezza di
un chunk dati; il metodo statico utils::swapL viene richiamato in questo
modo....
fin.read(pBuf, CHUNKLEN);            // file length in BIG ENDIAN;
utils::swapL((long*)pBuf);                 // to low endian
dopo la conversione, *pBuf risulta il valore della lunghezza valido per
un'architettura low endian [tipo il mio linux-box su AMD K6].
Sarebbe carino avere una funzioncina simile per trattare i float....
P.S.: potreste per piacere emailarmi anche tramite l'indirizzo
luca.f...@hit.com
 ?
Ringrazio anticipatamente!!
Luca Fossato


La differenza tra low endian e big endian dovrebbe essere costituita solo
dal fatto che i byte sono scambiati in memoria (nel senso che il byte
meno significativo di un dato ha indirizzo minore dell'indirizzo del byte piu` 
significativo nel little endian, mentre il byte meno significativo ha 
indirizzo maggiore rispetto all'indirizzo del byte piu` significativo del dato
nel big endian). Questo sia per interi che per i float (in genere i float
vengono rappresentati secondo uno degli standard IEEE ma non ricordo il
numero; comunque credo che il discorso sul little endian- bigendian sia
indipendente da come viene rappresentato un float).
Se il ragionamento e` corretto si dovrebbe poter passare sempre da un dato
little endian a uno big endian (e viceversa) semplicemente scambiando i bytes
del dato, indipendentemente dal fatto che questo sia un intero o meno.
Conseguentemente dovrebbe poter essere usata una funzione del tipo
seguente:
/****************************************************************
*  flipAll - n byte flipping                                    *
*  PARAMETER:                                                   *
*       data - pointer to the first byte of the data to be      *
*               converted                                       *
*       n    - lenght of data in bytes                          *
*  RETURN VALUES:                                               *
*       no value                                                *
****************************************************************/
void flipAll(char *data, int n) {
    char *p;
    char tmp;
    int i;
    if  (n <= 1)   return;
    p = data;
    for(i = 0; i < n/2; i++) {
        tmp = *p;
        *p = *(data+n-1-i);
        *(data+n-1-i) = tmp;
        p++;
    }
}
da usarsi ad esempio come segue:
int main(void) {
    /* supponiamo che la macchina su cui gira 
       la funzione main sia little-endian;
    */
    float a=15.0;
    long double b=12.087;
    /* ora a e b contengono le rappresentazioni di 15.0 e
        12.087 in formato little endian */
    flipAll((char *)&a,sizeof(a));
    flipAll((char *)&b,sizeof(b));
    /* ora a e b contengono le rappresentazioni di 15.0 e
        12.087 in formato big endian */
    ...  /* qui posso ad esempio spedire tramite 
            socket su una macchina remota (big endian)
            a e b in formato big endian. In tal caso la
            macchina remota non dovra` fare alcuna conversione 
            per leggere i valori corretti (cioe` 15.0 e 12.087)
            di a e b
          */
    return 0;
}
Marco Guidi

Non sono d'accordo, per quanto ne so la rappresentazione dei numeri a
virgola mobile cambia da cpu a cpu, quindi forse ti conviene memorizzare il
numero in virgola fissa e quindi trasmetterlo.


No, secondo me su quasi tutte le architetture i numeri in virgola mobile
seguono lo standard IEE 754. C'e' caso pero' che io sia rimasto un po'
indietro con i tempi.
-- 
Zack
Stefano Zacchiroli
zacc...@cs.unibo.it
za...@comune.budrio.bo.it
ICQ# 33538863
"Never understimate the dark side"

 
Potresti fare un piccolo esempio (con codice) di cosa intendi per 
"memorizzare il  numero in virgola fissa" ?
Comunque se le cose stanno come dici tu, allora un programma del tipo
/* programma client */
int main(void) {
    ... /* dichiarazioni e definizioni varie */
    float dato =12.345;
 
#ifdef LITTLE_ENDIAN
    covertiABigEndian(&dato,sizeof(dato)); /* per quanto ne so io, i dati
                                              in rete devono essere spediti
                                              big endian */
#endif
 
    connettitiAlServer(...); /* prepara opportunamente il socket */
 
    spedisciVersoIlServer(&dato...); /* spedisce dato verso il server, tramite
                                        socket */
    return 0;
}
sarebbe sempre sbagliato, visto che il server potrebbe sempre avere una
rappresentazione dei float diversa da quella del client.
Non mi ero mai nemmeno posto il problema visto che ho sempre visto
implementazioni del tipo sopra, su varie architetture, comunicanti
tra loro. Pero` forse il tutto funzionava solo per caso, il che conferma
una mia tesi (cioe` che qualsiasi cosa faccia un programmatore, anche
le peggiori schifezze, il programma funzionera` comunque, tranne che nel
momento in cui lo si deve presentare al committente).
Marco Guidi.
 


Ok, penso che per il fine settimana indossero' la mia tutina da eroe_nerd e
mi mettero' a fare 4 conti con carta, penna, calc e ddd debugger
on screen.
Anche a casaccio dovrei riuscire a scrivere qualche linea di codice che mi
permetta di convertire *correttamente* i float letti dal chunk PNTS
dei file di Lightwave.
Oppure si potrebbe fare un reverse engineering del metodo Java
"DataInputStream.readFloat()"  [o magari girano i sorgenti ??] ;^) !!
Grazie comunque per l'attenzione!
Luca Fossato

Se per caso trasferisci i dati attraverso una rete TCP/IP, verifica se
non hai a disposizione la libreria XDR, che ti permetterebbe di gestire
questo tipo di problemi in modo relativamente semplice.
Ciao,
Nicola Musatti

 wrote in message
