c-fp16到fp32转换的严格混叠错误



我有一个用于fp16到fp32转换的函数

static float fp16_to_fp32(const short in){
signed int t1, t2, t3;
float out = 0;
t1 = (in & 0x7fff) << 13 + 0x38000000;
t2 = (in & 0x8000) << 16;
t3 = in & 0x7c00;

t1 = (t3==0 ? 0 : t1);
t1 |= t2;
*((unsigned int*)&out) = t1;

return out;
}

错误:取消引用类型化的punned指针将破坏严格的别名规则[-Weror=严格别名]在((unsigned int(&out(=t1

我该如何解决这个问题?(无法更改参数类型in(

您可以使用memcpy()来复制数据。

还要注意,+运算符的优先级高于<<运算符,因此行t1 = (in & 0x7fff) << 13 + 0x38000000;不会按预期工作。

#include <string.h> /* for memcpy() */
static float fp16_to_fp32(const short in){
signed int t1, t2, t3;
float out = 0;
t1 = ((in & 0x7fff) << 13) + 0x38000000; /* add parenthesis */
t2 = (in & 0x8000) << 16;
t3 = in & 0x7c00;

t1 = (t3==0 ? 0 : t1);
t1 |= t2;
memcpy(&out, &t1, sizeof(out)); /* use memcpy() for copying */

return out;
}

您可以通过union使用类型punning来躲避严格的混叠:

union type_punner
{
unsigned int i;
float f;
} out = {.i = t1};
return out.f;

这是假设int和float大小相同,所以它不是很容易移植的代码。

您也可以使用-fno-strict-aliasing进行编译。

尝试将out声明为浮点指针,然后返回*out

最新更新