Tanj
Tanj

Reputation: 1354

memcpy not doing as it is supposed to

I have this bit of code that is outputting the wrong results.

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

the output that I get is

bytes 0xc0000000 float -2.000001e+00

I am expecting to get

bytes 0xdeadbeef float -6.2598534e+18

edit #1 as was pointed out the endianness could be different which would result in the following

bytes 0xefbeadde float -1.1802469e+29

what I don't understand is the cast from float to unsigned int resulting in 0xc0000000 (the float in the same printf statement being -2.0000 I would attribute to compiler optimization)

this was working before on a different computer. It could be an architecture change.

Upvotes: 1

Views: 1979

Answers (5)

Andomar
Andomar

Reputation: 238296

To see the parameter promotion, change the declaration from float to double. On my machine, that prints:

bytes 0xefbeadde float -1.860545e+230

The 0xefbeadde is big-endian for deadbeaf. The last 4 bytes of the double are undefined, so the number displayed after float will vary.

You mentioned it worked on another computer, what kind of computer was that? Must've been small endian where sizeof(float) == sizeof(double) :)

Upvotes: 1

Artelius
Artelius

Reputation: 49119

See if this is any better:

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

Upvotes: 1

btmorex
btmorex

Reputation: 496

The "%x" in printf expects an unsigned int. You're giving it a float which is getting automatically converted and that's not what you want. You want to do something like:

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

Oh, and as someone else pointed out, if you're on x86 you're not going to see 0xdeadbeef, more like 0xefbeadde.

Upvotes: 2

Artyom
Artyom

Reputation: 31271

It is not problem of memcpy.

  1. float is allways converted to double when passed over ... of printf, so you just can't get 4 bytes on most of intel architectures.
  2. when you expacting 0xdeadbeef in this code, you assume that your architecture is BIG endian. There are many little endian architectures, for example Intel x86.

Upvotes: 8

anon
anon

Reputation:

You do realise that floats are promoted to double when passed to a variable parameters function like printf()? So when you say:

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

you are trying to treat what is really two 8-byte values like two 4-byte values, giving (I believe) undefined behaviour.

Upvotes: 6

Related Questions