Domanda

Ho questo bit di codice che sta producendo risultati sbagliati.

#include <stdio.h>
#include <string.h>

int main() 
{
  unsigned char bytes[4];
  float flt=0;

  bytes[0]=0xde;
  bytes[1]=0xad;
  bytes[2]=0xbe;
  bytes[3]=0xef;

  memcpy( &flt, bytes, 4);

  printf("bytes 0x%x float %e\n", flt, flt);
  return 0;
}

l'output che ottengo è

  

byte 0xc0000000 float -2.000001e + 00

Mi aspetto di ottenere

  

byte 0xdeadbeef float -6.2598534e + 18

modifica n. 1 come è stato sottolineato, l'endianità potrebbe essere diversa e ciò comporterebbe il seguente

  

byte 0xefbeadde float -1.1802469e + 29

quello che non capisco è il cast da float a unsigned int che risulta in 0xc0000000 (il float nella stessa istruzione printf è -2.0000 che attribuirei all'ottimizzazione del compilatore)

prima funzionava su un altro computer. Potrebbe essere un cambiamento di architettura.

È stato utile?

Soluzione

Non è un problema di memcpy.

  1. float viene sempre convertito in double quando viene passato su ... di printf, quindi non è possibile ottenere 4 byte sulla maggior parte delle architetture Intel.
  2. quando ti aspetti 0xdeadbeef in questo codice, supponi che la tua architettura sia BIG endian. Esistono molte piccole architetture endian, ad esempio Intel x86.

Altri suggerimenti

Ti rendi conto che i float sono promossi a raddoppiare quando passati a una variabile parametri funzionano come printf ()? Quindi quando dici:

printf("bytes 0x%x float %e\n", flt, flt);

stai provando a trattare quelli che in realtà sono due valori a 8 byte come due 4 byte valori, dando (credo) un comportamento indefinito.

Il "% x " in printf prevede un int senza segno. Gli stai dando un float che viene convertito automaticamente e non è quello che vuoi. Vuoi fare qualcosa del tipo:

printf("bytes 0x%x float %e\n", *((unsigned int *)&flt), flt);

Oh, e come ha sottolineato qualcun altro, se sei su x86 non vedrai 0xdeadbeef, più come 0xefbeadde.

Vedi se è meglio:

printf("bytes 0x%x float %e\n", *(int *)&flt, flt);

Per vedere la promozione dei parametri, cambia la dichiarazione da float a double. Sulla mia macchina, che stampa:

bytes 0xefbeadde float -1.860545e+230

0xefbeadde è big-endian per deadbeaf. Gli ultimi 4 byte del doppio non sono definiti, quindi il numero visualizzato dopo il float varierà.

Hai detto che funzionava su un altro computer, che tipo di computer era? Deve essere stato un piccolo endian dove sizeof (float) == sizeof (double) :)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top