macalaca
macalaca

Reputation: 1048

What is wrong with this int to float conversion in C?

I'm confused by the output of the following bit of code:

float a  = 1.32;
int* b;
b= &a;
printf("%d", *b);

This bit of code turns the float into an int, but the output I'm getting is: 1068037571

Is this related to the IEEE 754 converting capabilities of the computer? Thanks!

Upvotes: 2

Views: 3787

Answers (3)

Floris
Floris

Reputation: 46365

What you are doing with your code is taking a peek at the way the floating point number is stored. A floating point takes up 4 bytes in memory (usually), as follows (example from wikipedia):

enter image description here

When you run your code, you pretend that those bits are a four byte integer:

float a  = 1.32;
int* b;
b= &a;
printf("%d", *b);

If you want to see the hex representation, just do

printf("%08x", *b);

And you will get

3f9d70a4

meaning that the bit pattern was

00111111100111010111000010100100

Breaking it up:

0 01111111 00111010111000010100100

sign bit 0 exponent 01111111 fraction (1)00111010111000010100100

And you will find that binary number

100111010111000010100100 = 10317988

And that

10317988.0 / (4096.0*2048.0) = 1.23

UPDATE Complete program that shows exactly how to do this:

#include <stdio.h>
#include <math.h>
#include <stdint.h>

int main(void) {
  float a = 1.23;
  uint32_t *b = (uint32_t *)&a;

  uint32_t signbit;
  uint32_t exponent;
  uint32_t mantissa;
  uint32_t fpAsInt;

  fpAsInt = *b;

  signbit = (fpAsInt & 0x80000000) >> 31;
  exponent = (fpAsInt & 0x7F800000) >> 23 ;
  mantissa = (fpAsInt & 0x007FFFFF) | 0x00800000;
  printf("fpAsInt: 0x%08x\n", fpAsInt);
  printf("sign bit: %d\n", signbit);
  printf("exponent: 0x%02x\n",  exponent);
  printf("mantissa: 0x%03x\n",  mantissa);
  printf("the value is %10f\n", ((signbit == 1)?-1.0:1.0)*mantissa / pow(2.0, (127 - exponent + 23)));
  printf("the original value was %10f\n", a);
}

Prints the result

fpAsInt: 0x3f9d70a4
sign bit: 0
exponent: 0x7f
mantissa: 0x9d70a4
the value is 1.2300000191
the original value is 1.2300000191

It may seem like cheating that I use floating point math in the last line - valid criticism, but the point here is to show how the floating point is constructed, not how to use integer math to extract the value.

Note - I am assuming that the floating point number is the IEEE 4 byte representation. Also, I included some specific casting to get rid of compiler warnings. Only do this when you are sure you know what you are doing...

ONE MORE EDIT

It was pointed out that the code is still subject to undefined behavior. In an attempt to get around that, and still give you insights into the above, let's do this one more time. Now I am using the union of a bit array and a float to "legally" access the different elements - and am getting no warnings when compiling with -Wall -pedantic. This may still not be sufficient, but it's the best I know...

#include <stdio.h>
#include <math.h>
#include <stdint.h>

union ieee754_float
  {
    float f;

    /* This is the IEEE 754 single-precision format on a little-endian machine.  */
    struct
      {
        unsigned int mantissa:23;
        unsigned int exponent:8;
        unsigned int negative:1;
      } ieee;
    };

int main(void) {
  float a = 1.23;
  union ieee754_float *pa;
  pa = (union ieee754_float*)&a;

  uint32_t signbit;
  uint32_t exponent;
  uint32_t mantissa;

  signbit = pa->ieee.negative;
  exponent = pa->ieee.exponent;
  mantissa = pa->ieee.mantissa | 0x00800000;
  printf("sign bit: %d\n", signbit);
  printf("exponent: 0x%02x\n",  exponent);
  printf("mantissa: 0x%03x\n",  mantissa);
  printf("the value is %.10f\n", ((signbit == 1)?-1.0:1.0)*mantissa / pow(2.0, (127 - exponent + 23)));
  printf("the original value is %.10f\n", a);
}

Upvotes: 7

Eric Lippert
Eric Lippert

Reputation: 659956

Many questions in the C tag on StackOverflow can be answered by going back to these basic rules:

  • & takes a variable and produces a pointer
  • * takes a pointer and produces a variable

So you said "take this float variable and make me a pointer. Now take that pointer and make me an int variable." You never said "take this float value and make me an int value". You said "take a pointer that can be turned into a float variable and turn it into an int variable instead". What happens when you do that? That is entirely up to the compiler to decide.

Upvotes: 2

David Heffernan
David Heffernan

Reputation: 612794

Your program invokes undefined behaviour. You are simply reinterpreting the representation of the float as an int. You are categorically not converting an int to a float. You cannot expect any particular behaviour.

To convert the float into an int you would use code like this:

int b = a;

which truncates the float to an int.

Upvotes: 11

Related Questions