Pregunta

Tengo este bit de código que genera resultados incorrectos.

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

el resultado que obtengo es

  

bytes 0xc0000000 flotante -2.000001e + 00

Estoy esperando obtener

  

bytes 0xdeadbeef float -6.2598534e + 18

editar # 1 como se señaló, el endianness podría ser diferente, lo que resultaría en lo siguiente

  

bytes 0xefbeadde float -1.1802469e + 29

lo que no entiendo es la conversión de float a unsigned int que resulta en 0xc0000000 (el float en la misma instrucción printf es -2.0000 que atribuiría a la optimización del compilador)

esto estaba funcionando antes en una computadora diferente. Podría ser un cambio de arquitectura.

¿Fue útil?

Solución

No es un problema de memcpy.

  1. float siempre se convierte a double cuando se pasa sobre ... de printf, por lo que no puede obtener 4 bytes en la mayoría de las arquitecturas de inteligencia.
  2. cuando expande 0xdeadbeef en este código, asume que su arquitectura es GRANDE endian. Hay muchas pequeñas arquitecturas endianas, por ejemplo Intel x86.

Otros consejos

¿Te das cuenta de que los flotadores se promueven al doble cuando se pasan a una función de parámetros variables como printf ()? Entonces cuando dices:

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

está tratando de tratar lo que en realidad son dos valores de 8 bytes como dos de 4 bytes valores, dando (creo) un comportamiento indefinido.

El "% x " en printf espera un int sin signo. Le estás dando un flotador que se convierte automáticamente y eso no es lo que quieres. Quiere hacer algo como:

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

Ah, y como alguien más señaló, si estás en x86 no verás 0xdeadbeef, más como 0xefbeadde.

Vea si esto es mejor:

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

Para ver la promoción del parámetro, cambie la declaración de flotante a doble. En mi máquina, eso imprime:

bytes 0xefbeadde float -1.860545e+230

El 0xefbeadde es big-endian para deadbeaf. Los últimos 4 bytes del doble no están definidos, por lo que el número que se muestra después del flotante variará.

Mencionaste que funcionaba en otra computadora, ¿qué tipo de computadora era esa? Debe haber sido un pequeño endian donde sizeof (float) == sizeof (double) :)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top