Casting an array of unsigned chars to an array of floats
Solution 1
I think the best way is to use a function object:
template <typename T> // T models Any
struct static_cast_func
{
template <typename T1> // T1 models type statically convertible to T
T operator()(const T1& x) const { return static_cast<T>(x); }
};
followed by:
std::transform(char_buff, char_buff + len, float_buff, static_cast_func<float>());
std::transform(float_buff, float_buff + len, char_buff, static_cast_func<unsigned char>());
This is the most readable because it says what is being done in English: transforming a sequence into a different type using static casting. And future casts can be done in one line.
Solution 2
Your solution is pretty much the best option, however, I would consider switching to:
char_buff[i]= static_cast<unsigned char>(float_buff[i]);
Solution 3
Your solution seems right, though on the way back, you might lose the floating digits in the casting.
Solution 4
For what purpose are you doing this? Shoving a float into a char doesn't really make sense. On most platforms a float will be 4 bytes and represent a floating point number, where as a char will be 1 byte and often represents a single character. You'll lose 3 bytes of data trying to shove a float into a char, right?
Solution 5
Your first loop doesn't require a cast. You can implicitly convert from one type (e.g., unsigned char
) to a wider type (e.g., float
). Your second loop should use static_cast
:
for (i=0; i< len; i++)
char_buff[i]= static_cast<unsigned char>(float_buff[i]);
We use static_cast
to explicitly tell the compiler to do the conversion to a narrower type. If you don't use the cast, your compiler might warn you that the conversion could lose data. The presence of the cast operator means that you understand you might lose data precision and you're ok with it. This is not an appropriate place to use reinterpret_cast
. With static_cast
, you at least have some restrictions on what conversions you can do (e.g., it probably won't let you convert a Bird*
to a Nuclear_Submarine*
). reinterpret_cast
has no such restrictions.
Also, here's what Bjarne Stroustrup has to say about this subject.
Admin
Updated on June 04, 2022Comments
-
Admin almost 2 years
What is the best way of converting a unsigned char array to a float array in c++?
I presently have a for loop as follows
for (i=0 ;i< len; i++) float_buff[i]= (float) char_buff[i];
I also need to reverse the procedure, i.e convert from unsigned char to float (float to 8bit conversion)
for (i=0 ;i< len; i++) char_buff[i]= (unsigned char) float_buff[i];
Any advice would be appreciated
Thanks
-
Admin about 15 yearsThanks I need to convert from float to 8bit
-
Michael Burr about 15 yearsThe cast will perform a conversion - truncating the fractional portion of the float away. This may be exactly what the person wants. One key thing to be aware of is that if the integral portion of the float can't be represented in an unsigned char (generally if it's not in the range 0-255) it's undefined.
-
Admin about 15 yearsThanks Michael, I dont mind losing the fractional part. If the float is less than 255, will the cast work OK? I was going to clamp the result to 255 if the float was greater than this. Thanks
-
Steve Jessop about 15 years@miki: The cast will work if the float value is in the range of unsigned char. That's almost always 0..255, but it might very rarely be something different. As long as you clamp the float to the range 0 to UCHAR_MAX before casting, the result is defined. Otherwise you get undefined behaviour.
-
Steve Jessop about 15 yearsOr std::copy(char_buff, char_buff+len, float_buff);
-
Gal Goldman about 15 yearsIn case the float is bigger than 255, it will have the MOD result after the cast (same as with any other overflow). For example: float = 500 -> char = 254. float = 256 -> char = 0. BTW, here's some info on static_cast: stackoverflow.com/questions/103512/…
-
Michael Burr about 15 yearsThe behavior if the float is >= 256 is undefined - getting a modulo value might well be common, but it's not guaranteed.
-
Mark Ruzon about 15 yearsUsing std::copy here exposes a flaw in STL (as well as C++). When you make a copy of something, it should be true that copy == original. By relying on implicit casting, this is no longer true, which is why implicit casting should be avoided.
-
Steve Jessop about 15 yearsIn which case: template<typename I, typename O> O convert(I start, I end, O dst) { return std::copy(start,end,dst); } ... convert(char_buf, char_buff+len, float_buff)