fp16 到 fp32 转换的严格别名错误

Strict aliasing error for fp16 to fp32 conversion

我有一个 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;
}

错误:取消引用类型双关指针将违反严格别名规则[-Werror=strict-aliasing] 在 ((unsigned int)&out) = t1;

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

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

您可以使用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 使用类型双关来避免严格的别名:

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

这假设 int 和 float 的大小相同,因此它不是非常可移植的代码。

你也可以用-fno-strict-aliasing编译。