C 返回的简化版本((union{float v;uint32_t r;}){(int)x}.r>;>;21)-496
我在malloc.c实现中发现了一些代码,有人能告诉我这些代码的实际用途吗:C 返回的简化版本((union{float v;uint32_t r;}){(int)x}.r>;>;21)-496,c,C,我在malloc.c实现中发现了一些代码,有人能告诉我这些代码的实际用途吗: return ((union { float v; uint32_t r; }){(int)x}.r>>21) - 496 我做了一些搜索,发现它将整数转换为IEEE 754浮点,但我无法理解它是如何工作的。有谁能帮助我分多个步骤理解它吗?这部分是: 基本上是从铸造为int的变量转换为float(联合的第一个成员) 将此float用作uint32\u t: .r 并删除最后21位(尾数?): 然后返回值
return ((union { float v; uint32_t r; }){(int)x}.r>>21) - 496
我做了一些搜索,发现它将整数转换为IEEE 754浮点,但我无法理解它是如何工作的。有谁能帮助我分多个步骤理解它吗?这部分是:
基本上是从铸造为int
的变量转换为float
(联合的第一个成员)
将此float
用作uint32\u t
:
.r
并删除最后21位(尾数?):
然后返回值-496
逐步:
union t {
float v;
uint32_t r;
};
union t u;
u.v = (int)x;
u.r >>= 21;
return u.r - 496;
这看起来像是计算4*log2x+12的一点小技巧,或者是非常接近这个值的东西
其思想是使用硬件来计算二进制对数,并使用位移位来获取浮点的指数部分以及尾数的两个高位
我编写了一个小测试程序来比较上面的计算:
#include <stdio.h>
#include <stdint.h>
#include <math.h>
int makesize(uint32_t x) {
return ((union { float v; uint32_t r; }){(int)x}.r>>21) - 496;
}
int main(void) {
for (uint32_t i = 1 ; i != 1000 ; i++) {
double v = i;
double x = log(v)/log(2);
int y = makesize(i);
int res= 12+((int)floor(4*x));
printf("%04d : %d,%d (%d)\n", i, y, res, y-res);
}
return 0;
}
#包括
#包括
#包括
int makesize(uint32\u t x){
返回((并集{float v;uint32_t r;}){(int)x}.r>>21)-496;
}
内部主(空){
对于(uint32_t i=1;i!=1000;i++){
双v=i;
双x=对数(v)/对数(2);
int y=制造尺寸(i);
内部分辨率=12+((内部)楼层(4*x));
printf(“%04d:%d,%d(%d)\n”,i,y,res,y-res);
}
返回0;
}
从1到999的运行产生的值彼此相差不超过1。您了解多少?位移位和496的减法是让你困惑的部分吗?(顺便说一句,我喜欢这个问题。我不确定它是否在主题上,但我觉得它很有趣。:)@student你想告诉我们x是什么类型(size\u t
,我猜),函数的返回类型是什么(int
我猜在这里)。否则你的问题无法回答。不,我认为你错过了一个关键点。由于初始化器列表{(int)x}
不包含成员指示符,因此其元素初始化联合的第一个成员,即v
。这涉及从int
到float
的转换。然后通过成员r
读取结果。关于为什么x
被转换为int
,而不是转换为无符号类型,有什么猜测吗?或者说真的,为什么它需要被施放?@JohnBollinger我不知道x
的类型。我将OP的计算包装在一个函数中,并给出了x
类型的uint32\u t
,因为我错过了OP代码中的强制转换。OP没有提供查看原始代码的方法,所以我不得不猜测类型。这很公平。我只是注意到(1)负参数的对数未定义,(2)由于代码来自malloc()
实现,x
不太可能具有实类型,(3)如果x
具有整数类型,那么强制转换的唯一净效果就是可能调用实现定义的行为。然而,我突然想到,x
可能有指针类型。这可以解释强制转换,尽管这不是为什么选择int
而不是无符号整数类型。
union t {
float v;
uint32_t r;
};
union t u;
u.v = (int)x;
u.r >>= 21;
return u.r - 496;
#include <stdio.h>
#include <stdint.h>
#include <math.h>
int makesize(uint32_t x) {
return ((union { float v; uint32_t r; }){(int)x}.r>>21) - 496;
}
int main(void) {
for (uint32_t i = 1 ; i != 1000 ; i++) {
double v = i;
double x = log(v)/log(2);
int y = makesize(i);
int res= 12+((int)floor(4*x));
printf("%04d : %d,%d (%d)\n", i, y, res, y-res);
}
return 0;
}