是否有一种定义明确且性能良好的方法将 double 按位转换为 uint64_t 并返回
Is there a well-defined and performant way to bitwise convert double to uint64_t and back
之前没有回答我问题的类似问题:
我需要将 double
保存到 STM32L476 微控制器上的闪存中。闪存控制器以 64 位块工作,来自 ST 的 HAL API 为要写入的数据采用 uint64_t
参数。为此,我需要将 double 变量中的位转换为一个或多个 uint64_t
s.
我尝试了以下,这是 UB:
uint64_t flash_write_val = *(uint64_t*)&double_value;
但是,我收到有关违反严格别名规则的编译器警告。如果不调用 UB,我将如何执行此操作?它不需要超级便携。它只能在 Cortex M4F 内核上有效。
我在考虑这个:
union uint64_double {
uint64_t flash_friendly;
double math_friendly;
};
这是一个好方法,还是我还在搬起石头砸自己的脚?
只需使用 memcpy
将字节复制到您想要的位置。
memcpy(&flash_write_val, &double_val, sizeof(double_val));
只有Cortex-M3+的答案!!
- 指针双关。
uint64_t flash_write_val = *(uint64_t*)&double_value;
由于 Cortex-M3 和更新版本支持非对齐访问,上述内容是 100% 安全的。我个人比较喜欢memcpy
的方式,但是在FLASH写函数的时候我一般都是用指针双关
- Union punning - 安全便携:
union uint64_double {
uint64_t flash_friendly;
double math_friendly;
};
memcpy
函数
最可移植且可能最有效的方法,因为现代编译器非常了解 memcpy
的作用,并且在许多情况下内联它。
uint64_t bar(uint64_t *);
uint64_t foo(double double_val)
{
uint64_t flash_write_val;
memcpy(&flash_write_val, &double_val, sizeof(flash_write_val));
return bar(&flash_write_val);
}
foo:
push {lr}
sub sp, sp, #12
mov r2, r0
mov r3, r1
mov r0, sp
strd r2, [sp]
bl bar
add sp, sp, #12
ldr pc, [sp], #4
之前没有回答我问题的类似问题:
我需要将 double
保存到 STM32L476 微控制器上的闪存中。闪存控制器以 64 位块工作,来自 ST 的 HAL API 为要写入的数据采用 uint64_t
参数。为此,我需要将 double 变量中的位转换为一个或多个 uint64_t
s.
我尝试了以下,这是 UB:
uint64_t flash_write_val = *(uint64_t*)&double_value;
但是,我收到有关违反严格别名规则的编译器警告。如果不调用 UB,我将如何执行此操作?它不需要超级便携。它只能在 Cortex M4F 内核上有效。
我在考虑这个:
union uint64_double {
uint64_t flash_friendly;
double math_friendly;
};
这是一个好方法,还是我还在搬起石头砸自己的脚?
只需使用 memcpy
将字节复制到您想要的位置。
memcpy(&flash_write_val, &double_val, sizeof(double_val));
只有Cortex-M3+的答案!!
- 指针双关。
uint64_t flash_write_val = *(uint64_t*)&double_value;
由于 Cortex-M3 和更新版本支持非对齐访问,上述内容是 100% 安全的。我个人比较喜欢memcpy
的方式,但是在FLASH写函数的时候我一般都是用指针双关
- Union punning - 安全便携:
union uint64_double {
uint64_t flash_friendly;
double math_friendly;
};
memcpy
函数 最可移植且可能最有效的方法,因为现代编译器非常了解memcpy
的作用,并且在许多情况下内联它。
uint64_t bar(uint64_t *);
uint64_t foo(double double_val)
{
uint64_t flash_write_val;
memcpy(&flash_write_val, &double_val, sizeof(flash_write_val));
return bar(&flash_write_val);
}
foo:
push {lr}
sub sp, sp, #12
mov r2, r0
mov r3, r1
mov r0, sp
strd r2, [sp]
bl bar
add sp, sp, #12
ldr pc, [sp], #4