2010-05-06 19 views
11

È possibile convertire float da big a little endian? Ho un grande valore endian da una piattaforma PowerPC che sto inviando via TCP a un processo di Windows (little endian). Questo valore è un float, ma quando I memcpy il valore in un tipo float Win32 e quindi chiama su tale valore, ottengo sempre 0,0000?Conversione di valori float da big endian a little endian

Cosa sto sbagliando?

+0

un'occhiata a questa domanda: http://stackoverflow.com/questions/1786137/c-serialization-of-the-floating-point-numbers-floats-doubles – Drakosha

+0

* think * che siano entrambi i formati IEEE, ma dovresti ricontrollare. –

+0

Cosa succede se non chiamate '_byteswap_ulong'? –

risposta

23

semplicemente invertire i quattro byte fabbrica

float ReverseFloat(const float inFloat) 
{ 
    float retVal; 
    char *floatToConvert = (char*) & inFloat; 
    char *returnFloat = (char*) & retVal; 

    // swap the bytes into a temporary buffer 
    returnFloat[0] = floatToConvert[3]; 
    returnFloat[1] = floatToConvert[2]; 
    returnFloat[2] = floatToConvert[1]; 
    returnFloat[3] = floatToConvert[0]; 

    return retVal; 
} 
+0

che l'ha fatto! Grazie! – Blade3

+0

Questo si interromperà su gcc con ottimizzazioni dovute all'aliasing del puntatore. Non farlo, usa l'unione per questo tipo di casting. Sono stato lì, l'ho colpito. – Tomek

+7

Questo è un codice C perfettamente legale e nessun compilatore dovrebbe romperlo.L'ho testato con VC6, Visual Studio 2008, Visual Studio 2010 e C++ Builder 2010. Nessuno di questi compilatori infrange questo codice. –

1

Potrebbe essere più semplice utilizzare il ntoa e funzioni correlate convertire da rete per ospitare e da host a network..the vantaggio sarebbe portatile. Here è un collegamento a un articolo che spiega come farlo.

1

Non memcpy i dati direttamente in un tipo float. Mantenerlo come char dati, scambiare i byte e quindi trattarlo come un float.

7

Ho trovato qualcosa di simile a questo molto tempo fa. Era buono per un ridere, ma ingerire a proprio rischio e pericolo. Non ho nemmeno compilato:

void * endian_swap(void * arg) 
{ 
    unsigned int n = *((int*)arg); 
    n = ((n >> 8) & 0x00ff00ff) | ((n << 8) & 0xff00ff00); 
    n = ((n >> 16) & 0x0000ffff) | ((n << 16) & 0xffff0000); 
    *arg = n; 

    return arg; 
} 
+0

Heh heh. Sapeva che sarebbe stato downvoted. L'ho pubblicato solo per la risatina. Quando ho intervistato molti EA alla EA molti anni fa, avevano una versione che faceva i turni in 1, 2, 4, 8, poi 16 bit di larghezza e chiedeva cosa faceva. – Sniggerfardimungus

+0

Questo interromperà anche con l'ottimizzazione in quanto rompe le rigide regole di aliasing ... – Tomek

+0

Prima di tutto, penso che fosse abbastanza chiaro che questo non era altro che un piccolo divertimento. In secondo luogo, non sono sicuro che si applichino le regole di aliasing. Mentre esiste la possibilità che * arg possa puntare alla memoria che sarà di proprietà di n, l'ottimizzatore non lo troverà rilevante, dal momento che non usa mai n di nuovo dopo aver assegnato a * arg. Le regole di aliasing non entrano in vigore finché non si fa qualcosa di simile: a = 5; * b = 7; c = a + (* b) ;, dove il valore di c non può essere calcolato da un valore memorizzato nella cache di a perché l'assegnazione a * b potrebbe averlo influenzato. Anche se avrei dovuto dire * ((int *) arg) = n; =] – Sniggerfardimungus

0

Questo valore è un galleggiante, ma quando ho "memcpy" il valore in un tipo float win32 e quindi chiamare _byteswap_ulong su quel valore, ho sempre arrivare 0.0000?

Questo dovrebbe funzionare. Puoi pubblicare il codice che hai?

Tuttavia, se ti interessa le prestazioni (forse non lo fai, in questo caso puoi ignorare il resto), dovrebbe essere possibile evitare la memcpy, caricandola direttamente nella posizione di destinazione e scambiando i byte lì, o utilizzando uno swap che esegue lo swapping durante la copia.

-2

Un buon modo per ottenere il valore è utilizzare struct.pack/unpack.
È possibile utilizzare il carattere ">" nel formato per indicare che i byte sono al contrario (big endian).

from struct import unpack, pack 
sebytes = '\xc8\x00\x00\x00' 
print unpack('l', sebytes) 
bebytes = '\x00\x00\x00\xc8' 
print unpack('>l', bebytes) 

uscita:

(200,) 
(200,) 
+0

Non C++ come per il tag domanda –

3

Ecco una funzione può invertire l'ordine dei byte di qualsiasi tipo.

template <typename T> 
T bswap(T val) { 
    T retVal; 
    char *pVal = (char*) &val; 
    char *pRetVal = (char*)&retVal; 
    int size = sizeof(T); 
    for(int i=0; i<size; i++) { 
     pRetVal[size-1-i] = pVal[i]; 
    } 

    return retVal; 
} 
Problemi correlati