Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
479 views
in Technique[技术] by (71.8m points)

c++ - Is it safe to reinterpret_cast an integer to float?

Note: I mistakenly asked about static_cast originally; this is why the top answer mentions static_cast at first.

I have some binary files with little endian float values. I want to read them in a machine-independent manner. My byte-swapping routines (from SDL) operate on unsigned integers types.

Is it safe to simply cast between ints and floats?

float read_float() {
    // Read in 4 bytes.
    Uint32 val;
    fread( &val, 4, 1, fp );
    // Swap the bytes to little-endian if necessary.
    val = SDL_SwapLE32(val);
    // Return as a float
    return reinterpret_cast<float &>( val );  //XXX Is this safe?
}

I want this software to be as portable as possible.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Well, static_cast is "safe" and it has defined behavior, but this is probably not what you need. Converting an integral value to float type will simply attempt to represent the same integral value in the target floating-point type. I.e. 5 of type int will turn into 5.0 of type float (assuming it is representable precisely).

What you seem to be doing is building the object representation of float value in a piece of memory declared as Uint32 variable. To produce the resultant float value you need to reinterpret that memory. This would be achieved by reinterpret_cast

assert(sizeof(float) == sizeof val);
return reinterpret_cast<float &>( val );

or, if you prefer, a pointer version of the same thing

assert(sizeof(float) == sizeof val);
return *reinterpret_cast<float *>( &val );

Although this sort of type-punning is not guaranteed to work in a compiler that follows strict-aliasing semantics. Another approach would be to do this

float f;

assert(sizeof f == sizeof val);
memcpy(&f, &val, sizeof f);

return f;

Or you might be able to use the well-known union hack to implement memory reinterpretation. This is formally illegal in C++ (undefined behavior), meaning that this method can only be used with certain implementations that support it as an extension

assert(sizeof(float) == sizeof(Uint32));

union {
  Uint32 val; 
  float f;
} u = { val };

return u.f;

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...