将浮点数 32 位变量类型转换为无符号整数 32 位时进行了哪些位级更改

What bit-level-changes are made while typecasting a float 32bit variable to unsigned integer 32bit?

本文关键字:变量 浮点数 类型转换 无符号整数      更新时间:2023-10-16

考虑我想将浮点数 32 位数据类型转换为无符号整数 32 位。

float foo = 5.0f;  
uint32 goo;
goo = (uint32)foo;

编译器如何对变量进行类型转换?是否有任何中间步骤;如果是,它们是什么?

这将在很大程度上取决于硬件(尽管像操作系统/编译器这样的东西可以并且将会改变硬件的使用方式)。

例如,在较旧的英特尔处理器(以及当前处理器,在大多数 32 位代码中)上,您将 x87 指令集用于(大多数)浮点数。在这种情况下,有一个支持存储为整数的fistp(浮点整数存储和 pop,尽管还有一个非弹出变量,以防您还需要继续使用该浮点值),因此这是通常使用的。浮点控制字中有一个位控制转换的完成方式(舍入与截断),也必须正确设置。

在当前硬件上(当前编译器生成 64 位代码),您通常会使用 SSE 指令,在这种情况下,可以使用 cvtss2si 完成对有符号 int 的转换。

不过,这些都不直接支持无符号操作数(至少我确定 SSE 不支持,据我所知,x87 也不支持)。对于这些,编译器可能在库中有一个小函数,所以它(至少部分)在软件中完成。

如果您的编译器支持生成 AVX256/AVX512 指令,它可以使用 VCVTTSS2USI 从 32 位浮点数转换为 64 位整数,然后将该整数的底部 32 位存储到您的目标(如果结果为负数或太大而无法容纳 32 位整数,那么......标准说这给出了未定义的行为,所以你得到了你应得的)。

点数和无符号数以完全不同的格式存储,因此编译器必须从一个更改为另一个,而不是从无符号转换为有符号,其中数字的格式相同,软件只是改变数字的解释方式。

例如,在 32 位浮点数中,数字 5 表示为浮点数中的0x40a00000,0x00000005表示为无符号。

当您使用较弱的微控制器时,这种转换最终会很重要,在任何带有 FPU 的事物上,它都是一些额外的指令。

这是维基百科关于浮点的文章

这是一个浮点转换器,显示位电平数据

编译器

将负责这部分,例如在支持SSE FPU的英特尔架构上,GCC在"emmtrin.h"中定义了一些操作。

一个简单的方法是编译一个带有汇编输出的小c程序,你会得到类似的东西:

 movss -4(%rbp), %xmm0
 cvtps2pd  %xmm0, %xmm0
 movsd .LC1(%rip), %xmm1
 addsd %xmm1, %xmm0
 cvttsd2si %xmm0, %eax

这里使用FPU相关指令(cvtps2pd/cvttsd2si),这完全取决于目标机器。