2010-11-04 31 views
7
#ifndef INFINITY 
#ifdef _MSC_VER 
    union MSVC_EVIL_FLOAT_HACK 
    { 
     unsigned __int8 Bytes[4]; 
     float Value; 
    }; 
    static union MSVC_EVIL_FLOAT_HACK INFINITY_HACK = {{0x00, 0x00, 0x80, 0x7F}}; 
    #define INFINITY (INFINITY_HACK.Value) 
#endif 

Attualmente sto ottenendo iniziato con il motore fisico Chipmunk e ho trovato questo in un file di intestazioneCosa fa questo codice?

INFINITY viene utilizzato per impostare lo slancio infinito per gli oggetti, ma non capisco che cosa questo codice di cui sopra fa!

risposta

6

Il codice sopra definisce effettivamente una costante in virgola mobile con una rappresentazione di byte molto specifica.

Ogni float è rappresentato con una serie di byte, ma quando si definiscono float costanti si è costretti a usare rappresentazione decimale e non si può definire una costante con il valore di dire 0xFFFFFFFF (non so se questa è una costante numero legale float).

Il codice sopra ignora tale limite: imposta prima un array di byte all'interno dell'unione e quindi "accede" allo stesso array di byte come se fosse un numero float. Questo a proposito è illegale: solo il membro del sindacato precedentemente impostato può essere legalmente accessibile, ma potrebbe funzionare su quella specifica implementazione.

15

Imposta INFINITY sul valore float rappresentato dai bit esadecimali 0x7f800000, ovvero +INF. Visual Studio non definisce INFINITY per qualche motivo.

+0

Inoltre, si precisa in ordine inverso {0x00, 0x00, 0x80, 0x7F} perché x86 utilizza little-endian. – jfs

+2

'questo '+/- INF' nella tua risposta?Perché sono abbastanza sicuro che il pattern a bit sia solo "+ Inf" :-) – paxdiablo

+0

Non importa, lo aggiusterò io stesso. Non posso sopportare una risposta sbagliata con così tanti voti :-) – paxdiablo

1

È un modo per inizializzare la memoria occupata da una variabile mobile su 0x7f800000. Come dice @Jim, questo è + infinito nel float.

Il codice è approssimativamente equivalente a:

byte Bytes[4] = { 0x00, 0x00, 0x80, 0x7F }; 
float Value; 
memcpy(&Value, Bytes, 4); 
#define INFINITY_HACK (Value) 

Innanzitutto il codice originale definisce un'unione che consente di manipolare quattro byte di memoria sia come un array di quattro byte, o come singolo galleggiante (che abbiamo assumere occupa anche quattro byte):

union MSVC_EVIL_FLOAT_HACK 
    { 
     unsigned __int8 Bytes[4]; 
     float Value; 
    }; 

Poi alloca un'istanza dell'unione denominato INFINITY_HACK e imposta i valori della sua matrice Bytes ai valori esadecimali specificati .:

static union MSVC_EVIL_FLOAT_HACK INFINITY_HACK = {{0x00, 0x00, 0x80, 0x7F}}; 

Ciò ha l'effetto di inizializzare il campo Valore float poiché occupa anche la stessa memoria dell'array di byte.

Infine definisce una costante proprocessor chiamato INFINITY come valore float.

2

Crea una variabile INFINITY_HACK, di tipo MSVC_EVIL_FLOAT_HACK. imposta la matrice Bytes per avere valori dei rispettivi valori esadecimali. Converte quindi quei byte in un numero a virgola mobile (unione consente solo di utilizzare uno dei valori sottostanti all'interno in modo da fare riferimento a .valore sta convertendo i dati a cui INIFITY_HACK punta, a float) seguendo lo IEEE-754 Floating-Point Standard (notare che il i byte sono presi al contrario) per la conversione binario-> float.

C'è un bel po 'di calcolatrice che può spiegare se non si sa come funziona: http://babbage.cs.qc.cuny.edu/IEEE-754/32bit.html (se si immette 7F800000, si otterrà Infinity, ma tenta di entrare 4048F5C2 (si arriva vicino a 3.14) This calculator va decimal-> esagonale.