在 C 中,我见过这段代码被用作操作浮点数的方法,具体到位:
union {
uint32_t bits;
float value;
}
通过定义这种类型的变量,可以在
var.bits
一侧执行按位运算,而 var.value
计算结果为浮点值本身,该值又可以在表达式中打印和使用。
但是,代码依赖于以下事实:
float
宽度与 unit32_t
大小相匹配。虽然通常是这种情况,但我很好奇如何在没有这样的假设的情况下实现此代码,即它根据浮点大小选择正确的固定宽度整数。
想到的一种方法是使用一堆
if
语句,并通过比较 sizeof(float)
和 stdint.h
宽度常量进行分支,例如:
if (sizeof(float) == sizeof(uint32_t))
typedef uint32_t CorrectInt;
else if (sizeof(float) == sizeof(uint64_t))
typedef uint64_t CorrectInt;
else ...
这段代码只有编译后才能运行。联合类型可以在全局范围内定义,但现在变量本身必须在本地声明。我更喜欢在类型声明本身之后全局声明并初始化变量本身,如下所示:
union {
uint32_t bits;
float val;
} var = {UINTMAX_C(1)};
所以分支方法行不通。
还有另一种方法可以为浮点数找到正确的固定宽度整数类型吗?
不是一个完整的解决方案,但却是一个开始:根据
float
的有效位计数来引导代码。FLT_XXX
属性进行优化。
#include <assert.h>
#include <float.h>
#include <stdint.h>
#if FLT_MANT_DIG <= 28
typedef uint32_t flt_int;
#elif FLT_MANT_DIG <= 28*2
typedef uint32_t flt_int;
#elif FLT_MANT_DIG <= 28*4
typedef uint64_t flt_int;
#else
#error TBD code
#endif
// If we got it wrong, stop the compilation.
static_assert(sizeof(float) == sizeof(flt_int), "TBD code");