Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/55.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 返回的简化版本((union{float v;uint32_t r;}){(int)x}.r>;>;21)-496_C - Fatal编程技术网

C 返回的简化版本((union{float v;uint32_t r;}){(int)x}.r>;>;21)-496

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位(尾数?): 然后返回值

我在malloc.c实现中发现了一些代码,有人能告诉我这些代码的实际用途吗:

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;
}