我无法理解这个联合数据类型
联合数据类型是程序员指示某个变量可以是多种不同类型之一的方法。 C11标准的措辞有点像“一个联盟最多包含一个成员”。它用于诸如逻辑上可能是这样或那样的参数之类的东西。例如,IP 地址可能是 IPv4 地址或 IPv6 地址,因此您可以按如下方式定义地址类型:
struct IpAddress
{
bool isIPv6;
union
{
uint8_t v4[4];
uint8_t v6[16];
} bytes;
}
你会这样使用它:
struct IpAddress address = // Something
if (address.isIPv6)
{
doSomeV6ThingWith(address.bytes.v6);
}
else
{
doSomeV4ThingWith(address.bytes.v4);
}
从历史上看,union
s 还用于将一种类型的位获取到另一种类型的对象中。这是因为,在联合中,成员都从相同的内存地址开始。如果我只是这样做:
float f = 3.0;
int i = f;
编译器将插入代码将浮点转换为整数,因此指数将丢失。然而,在
union
{
unsigned int i;
float f;
} x;
x.f = 3.0;
int i = x.i;
i
现在包含代表的确切位3.0
in a float
。或者至少你希望如此。 C 标准中没有任何内容说明float
and unsigned int
必须是相同的大小。 C 标准中也没有强制要求特定的表示形式float
(嗯,附件 F 说浮子符合 IEC 60559 ,但我不知道这是否算作标准的一部分)。所以上面的代码充其量是不可移植的。
获取a的指数float
便携式方式是frexpf() https://linux.die.net/man/3/frexp函数定义在math.h
我如何操纵 f2i 函数来达到此目的?
让我们假设一个float
以 32 位的 IEC 60559 格式存储,Wkipedia 认为与IEEE 754 https://en.wikipedia.org/wiki/Single-precision_floating-point_format。我们还假设整数以小端格式存储。
union
{
uint32_t i;
float f;
} x;
x.f = someFloat;
uint32_t bits = x.i;
bits
现在包含浮点数的位模式。单精度浮点数看起来像这样
SEEEEEEEEMMMMMMMMMMMMMMMMMMMMMMM
^ ^ ^
bit 31 bit 22 bit 0
Where S
是符号位,E
是一个指数位,M
是尾数位。
所以有了你的int32_t
你只需要做一些移位和掩蔽:
uint32_t exponentWithBias = (bits >> 23) & 0xff;