Zack Lee
Zack Lee

Reputation: 3044

How to cast double to float pointer?

I'm trying to cast double to float pointer but I don't know the proper way to do it.

Here's my code

#include <iostream>

int main(int argc, const char * argv[]) {
    // insert code here...


    float *f;
    double d = 10;

    f = reinterpret_cast<float*>(&d);
    d = 20;

    std::cout << "RESULT : " << *f << std::endl;
    return 0;
}

And I get the following result.

RESULT : 0
Program ended with exit code: 0

How do I properly cast double to float pointer?

ADD : The result I expect to get is 20

Upvotes: 5

Views: 12284

Answers (5)

DevSolar
DevSolar

Reputation: 70263

Consider:

#include <cstdio>
#include <cassert>

using namespace std;

int main()
{
    double d = 10;
    float f;
    assert( sizeof d == 8 );
    assert( sizeof f == 4 );

    unsigned char * d_ = (unsigned char *)&d;
    printf( "%hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx\n", d_[0], d_[1], d_[2], d_[3], d_[4], d_[5], d_[6], d_[7] );
}

This, at least on my machine, gives the following output:

0 0 0 0 0 0 24 40

Explanation:

That is the internal representation of a double with value 10.

By casting the double * to float *, you are only looking at the first four bytes of this -- 0 0 0 0. Do you see why you are getting a 0 output when you dereference the pointer?

(Aside from, as others have pointed out, the dereferencing of the pointer being undefined behaviour due to breaking strict aliasing.)

Solution:

What you probably want is to cast the value of d:

static_cast<float>(d);

You can then store that value in an object of the correct type:

float f = static_cast<float>(d);
float * fp = &f;

Upvotes: 9

MSalters
MSalters

Reputation: 179809

The behavior you want can be implemented in C++. Not via a raw pointer, though, but C++ allows user-defined types.

class double_as_float {
  double& d;
public:
  double_as_float(double& d) : d(d) { }
  float operator*() const { return static_cast<float>(d); }
};

Usage:

#include <iostream>
int main() {

    double d = 10;

    double_as_float f { d };
    d = 20;

    std::cout << "RESULT : " << *f << std::endl;
    return 0;
}

Upvotes: 1

Bathsheba
Bathsheba

Reputation: 234695

The behaviour is undefined: the language offers no way of doing this. For example, sizeof(float*) does not have to be the same as sizeof(double*). C++ aims to maximise flexibility.

You are allowed to cast the address of a double to a const unsigned char* pointer and read the memory that way.

Otherwise you need to resort to assembly, where at the CPU level, the distinction between a pointer to a type and an integral type is considerably blurred.

If you want to convert a double to a float, then write

double d = 10; float f = d;

Upvotes: 4

Jodocus
Jodocus

Reputation: 7581

What you want to do is a narrowing static_cast:

auto f = static_cast<float>(d);
float* pointer = &f;

The use of reinterpret_cast will fail, because it will not issue the compiler to change the bitwise representation of a double to that one of a float. It literally will reinterpret the double value as a float, yielding weird and undefined results as the representations differ. static_cast on the other side will take care for you that the representations are adjusted correctly, possibly truncating the least significant bits if necessary. After this, you can safely use the address of the float variable and access the value with a pointer.

Upvotes: 1

M.M
M.M

Reputation: 141554

Your code for casting the pointer is correct.

The mistake is *f, which causes undefined behaviour by violating the strict aliasing rule. You can not read or write through a pointer that has the wrong type for the object it points to. (with a small list of exceptions).

Upvotes: 4

Related Questions