2009-05-09 5 views
1

J'ai ce bit de code qui produit de mauvais résultats.memcpy ne pas faire comme il est censé

#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 flottant -2.000001e + 00

Je comptais obtenir

octets 0xDEADBEEF flotter -6.2598534e +18

modifier # 1 comme l'a souligné le boutisme pourrait être différente qui entraînerait les

octets suivants 0xefbeadde flotteur -1.1802469e + 29

ce que je ne comprends pas la transtyper de float en entier non signé résultant en 0xc0000000 (le flottant dans la même instruction printf étant -2.0000 j'attribuerais à l'optimisation du compilateur)

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

Répondre

8

Ce n'est pas un problème de memcpy.

  1. float est converti allways double lorsqu'il est passé sur ... de printf, vous donc ne pouvez pas obtenir 4 octets sur la plupart des architectures intel. Lorsque vous exposez 0xdeadbeef dans ce code, vous supposez que votre architecture est big endian. Il y a beaucoup d'architectures little endian, par exemple Intel x86.
+0

ne se rendent pas compte qu'il était un problème de printf pour la partie hexagonale. Je ne comprends pas comment le flotteur n'a pas été moulé correctement en double. – Tanj

+1

Lancer le flotteur pour doubler fait plus que déplacer quatre octets vers la droite: la conversion fait en sorte que 3,14 po de flottement soit 3,14 po de double. Et après une promotion à double, printf() est passé quatre octets, où le% x lui dit d'attendre 2 octets. Donc tout après% x est hors base. – Andomar

6

Vous réalisez que les flottants sont promus à doubler lorsqu'ils sont passés à une fonction de paramètres variables comme printf()? Alors, quand vous dites:

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

vous essayez de traiter ce qui est vraiment deux valeurs de 8 octets comme deux 4 octets valeurs, ce qui donne (je crois) un comportement non défini.

2

Le "% x" dans printf attend un entier non signé. 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 d'autre là, si vous êtes sur x86 vous n'êtes pas allez voir 0xdeadbeef, plus comme 0xefbeadde.

1

voir si cela est mieux:

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

Pour voir la promotion des paramètres, changer la déclaration du flotteur à double. Sur ma machine, cela imprime:

bytes 0xefbeadde float -1.860545e+230 

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

Vous en avez parlé a travaillé sur un autre ordinateur, quel type d'ordinateur était-ce? Petit endian a dû être où sizeof (float) == sizeof (double) :)

Questions connexes