Noah Roth
Noah Roth

Reputation: 9220

Convert pointer to float?

I have a unsigned char*. Typically this points to a chunk of data, but in some cases, the pointer IS the data, ie. casting a int value to the unsigned char* pointer (unsigned char* intData = (unsigned char*)myInteger;), and vice versa.

However, I need to do this with a float value, and it keeps giving me conversion errors.

unsigned char* data;
float myFloat = (float)data;

How can I do this?

Upvotes: 4

Views: 10216

Answers (4)

amdn
amdn

Reputation: 11582

If your compiler supports it (GCC does) then use a union. This is undefined behavior according to the C++ standard.

union {
    unsigned char* p;
    float f;
} pun;

pun.p = data;
float myFloat = pun.f;

This works if sizeof(unsigned char *) == sizeof(float). If pointers are larger than floats then you have to rethink your strategy.

See wikipedia article on type punning and in particular the section on use of a union.

GCC allows type punning using a union as long as you use the union directly and not typecasting to a union... see this IBM discussion on type-pun problems for correct and incorrect ways of using GCC for type punning.

Also see wikipedia's article on strong and weak typing and a well researched article on type punning and strict aliasing.

Upvotes: 2

bames53
bames53

Reputation: 88235

bit_cast:

template <class Dest, class Source>
inline Dest bit_cast(Source const &source) {
    static_assert(sizeof(Dest)==sizeof(Source), "size of destination and source objects must be equal");
    static_assert(std::is_trivially_copyable<Dest>::value, "destination type must be trivially copyable.");
    static_assert(std::is_trivially_copyable<Source>::value, "source type must be trivially copyable");

    Dest dest;
    std::memcpy(&dest, &source, sizeof(dest));
    return dest;
}

Usage:

char *c = nullptr;
float f = bit_cast<float>(c);
c = bit_cast<char *>(f);

Upvotes: 4

Kerrek SB
Kerrek SB

Reputation: 477670

The only correct way to use a given variable to store other data is to copy the data byte-wise:

template <typename T>
void store(unsigned char * & p, T const & val)
{
    static_assert(sizeof(unsigned char *) >= sizeof(T));

    char const * q = reinterpret_cast<char const *>(&val);
    std::copy(q, q + sizeof(T), reinterpret_cast<char *>(&p));
}

Usage:

unsigned char * p;
store(p, 1.5);
store(p, 12UL);

The matching retrieval function:

template <typename T>
T load(unsigned char * const & p)
{
    static_assert(sizeof(unsigned char *) >= sizeof(T));

    T val;
    char const * q = reinterpret_cast<char const *>(&p);
    std::copy(q, q + sizeof(T), reinterpret_cast<char *>(&val));

    return val;
}

Usage:

auto f = load<float>(p);

Upvotes: 3

Adrian Cornish
Adrian Cornish

Reputation: 23916

unsigned char* data;
float myFloat = *(float*)data;

Upvotes: -1

Related Questions