Question

J'ai ce bit de code qui génère des résultats erronés.

#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;
}

la sortie que je reçois est

  

octets 0xc0000000 float -2.000001e + 00

Je m'attends à recevoir

  

octets 0xdeadbeef float -6.2598534e + 18

modifier n ° 1 comme cela a été souligné, l’endianisme pourrait être différent, ce qui donnerait les résultats suivants

  

octets 0xefbeadde float -1.1802469e + 29

Ce que je ne comprends pas, c’est que la conversion de float en unsigned int a pour résultat 0xc0000000 (le float dans la même instruction printf étant égal à -2,0000, je l’attribuerais à l’optimisation du compilateur)

cela fonctionnait auparavant sur un autre ordinateur. Ce pourrait être un changement d'architecture.

Était-ce utile?

La solution

Ce n’est pas un problème de mémoire.

  1. float est toujours converti en double lorsqu'il est passé sur ... de printf, vous ne pouvez donc pas obtenir 4 octets sur la plupart des architectures intel.
  2. lorsque vous expliquez 0xdeadbeef dans ce code, vous supposez que votre architecture est BIG endian. Il existe de nombreuses architectures little endian, par exemple Intel x86.

Autres conseils

Vous vous rendez compte que les flottants sont doublés quand ils sont passés à une variable dont les paramètres fonctionnent comme printf ()? Alors, quand vous dites:

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

vous essayez de traiter deux valeurs de 8 octets comme deux valeurs de 4 octets valeurs, donnant (je crois) un comportement indéfini.

Le "%% <<>> quot; dans printf attend un unsigned int. Vous lui donnez un float qui est automatiquement converti et ce n'est pas ce que vous voulez. Vous voulez faire quelque chose comme:

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

Oh, et comme quelqu'un l'a fait remarquer, si vous êtes sur x86, vous n'allez pas voir 0xdeadbeef, plutôt comme 0xefbeadde.

Voir si c'est mieux:

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

Pour voir le paramètre promotion, changez la déclaration de float en double. Sur ma machine, cela affiche:

bytes 0xefbeadde float -1.860545e+230

0xefbeadde est big-endian pour deadbeaf. Les 4 derniers octets du double étant indéfinis, le nombre affiché après le flottant variera.

Vous avez mentionné que cela fonctionnait sur un autre ordinateur, de quel type d'ordinateur s'agissait-il? Doit avoir été petit endian où sizeof (float) == sizeof (double):)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top