在下面的代码中,我有bits正确的(它最初是bits<float>在C++程序中输入的,但我只是uint32在这个C程序中使用过.).我想将这些位用作ieee754 float值.分配只是float_var = int_val不会这样做,因为它解释了值并转换为float.我想只使用位值作为浮点值.
uint32 bits = mantissa_table[offset_table[value>>10]+(value&0x3FF)] + exponent_table[value>>10];
ab_printf("bits = %x\n", bits);
float out;
//memcpy(&out, &bits, sizeof(float)); // original
char *outp = &out;
char *bitsp = &bits;
outp[0] = bitsp[0];
outp[1] = bitsp[1];
outp[2] = bitsp[2];
outp[3] = bitsp[3];
ab_printf("out = %x\n", out);
return out;
Run Code Online (Sandbox Code Playgroud)
程序运行结果的一部分:
ff = 3.140000
hh = 4248
bits = 40490000
out = 40092000
Run Code Online (Sandbox Code Playgroud)
必须有一些我不知道的基本知识.为了您的信息,上面的运行是将浮动3.14转为半精度并返回单精度,我打印中间值.0x4248是半精度3.140625,位0x40490000也是单精度3.140625,所以我只需要将其返回为float.
ADD:在阅读了注释和答案之后,我做了一些实验,发现在函数内部看到单浮点值是正确的(使用指针或使用union的类型punning),但是当它返回到调用函数时,它是打印不正确.方法0~3都不起作用.内联函数与否没有任何区别.在我们的系统中可能存在另一个错误(嵌入式,裸机),但希望有人可以告诉我这里可能有什么问题.(我在这里使用C程序中的C++程序的一部分).(ldexp,ldexpf不起作用).
== half.h ==
typedef unsigned short uint16;
typedef unsigned short half;
extern uint16 float2half_impl(float value);
extern float half2float_impl(half value);
Run Code Online (Sandbox Code Playgroud)
== test4.c ==
#include "half.h"
int main()
{
float vflt = 3.14;
half vhlf;
float vflt2;
ab_printf("vflt = %f\n", vflt);
vhlf = float2half_impl(vflt);
ab_printf("vhlf = %x\n", *(unsigned short *)&vhlf);
float vflt2 = half2float_impl(vhlf);
ab_printf("received : vflt2 = %f\n", vflt2);
}
Run Code Online (Sandbox Code Playgroud)
== half.c ==
#include "half.h"
....
inline float half2float_impl(uint16 value)
{
//typedef bits<float>::type uint32;
typedef unsigned int uint32;
static const uint32 mantissa_table[2048] = {
....
uint32 bits = mantissa_table[offset_table[value>>10]+(value&0x3FF)] + exponent_table[value>>10];
ab_printf("bits = %x\n", bits);
float out;
#define METHOD 3
#if METHOD == 0
memcpy(&out, &bits, sizeof(float));
return out;
#elif METHOD == 1
#warning METHOD 1
ab_printf("xx = %f\n", *(float *)&bits); // prints 3.140625
return bits;
#elif METHOD == 2 // prints float ok but return value float prints wrong
#warning METHOD 2
union {
unsigned int ui;
float xx;
} aa;
aa.ui = bits;
ab_printf("xx = %f\n", aa.xx); // prints 3.140625
return (float)aa.xx; // but return values prints wrong
#elif METHOD == 3 // prints float ok but return value float prints wrong
#warning METHOD 3
ab_printf("xx = %f\n", *(float *)&bits); // prints 3.140625
return *(float *)&bits; // but return values prints wrong
#else
#warning returning 0
return 0;
#endif
}
Run Code Online (Sandbox Code Playgroud)
使用工会怎么样?
union uint32_float_union
{
uint32_t i;
float f;
};
Run Code Online (Sandbox Code Playgroud)
然后你可以做类似的事情
union uint32_float_union int_to_float;
int_to_float.i = bits;
printf("float value = %f\n", int_to_float.f);
Run Code Online (Sandbox Code Playgroud)
C规范明确允许使用联合进行类型惩罚.
memcpy你注释掉的方式应该有效,但确实打破了严格的别名.您可以使用字节缓冲区作为中间件:
char buffer[sizeof(float)];
memcpy(buffer, &bits, sizeof(float));
float value;
memcpy(&value, buffer, sizeof(float));
Run Code Online (Sandbox Code Playgroud)
当然,所有这些都要求值bits实际上对应于有效值float(包括正确的字节序).