c - 在 C 中将 float 转换为处理器内部的 int

标签 c optimization casting floating-point x87

<分区>

我对编译器如何通过如下指令将 float 转换为 int 很感兴趣:

    float x_f = 3.1415
    int x = (int)x_f;

尤其是速度。它像内置处理器指令一样超快吗?还是需要计算?

如果 float 总是包含一个精确的整数(例如:x_f = 3.0000),我也会想知道它是否改变了什么。

编辑:这个问题是针对在英特尔 x86 处理器上使用的 gcc 编译器的。

EDIT2:如果 x_f = 3.0 它会改变什么吗?

最佳答案

这在很大程度上取决于特定的 cpu。由于你对x86感兴趣,原来的387 fpu有一个将float转换为整数的指令,但是不能直接使用,因为它使用默认的舍入模式,而C中的转换需要截断,而不是舍入。因此,以下函数:

int f(float x)
{
    return x;
}

编译为(使用 gcc -O3 -fno-asynchronous-unwind-tables,以避免 asm 中的 crud):

        .text
        .p2align 4,,15
        .globl  f
        .type   f, @function
f:
        subl    $8, %esp
        fnstcw  6(%esp)
        movw    6(%esp), %ax
        movb    $12, %ah
        movw    %ax, 4(%esp)
        flds    12(%esp)
        fldcw   4(%esp)
        fistpl  (%esp)
        fldcw   6(%esp)
        movl    (%esp), %eax
        addl    $8, %esp
        ret

它的作用是保存、更改和恢复 fpu 控制字以更改舍入模式。

另一方面,如果您正在为具有可用于浮点的 SSE 的目标构建,您将获得:

        .text
        .globl  f
        .type   f, @function
f:
        cvttss2si       4(%esp), %eax
        ret

所以,这真的取决于。

最后,由于您提到您对值已经是整数的情况特别感兴趣,所以这没有任何区别。要转换的 cpu 操作几乎肯定不在乎。然而,在这种情况下,可以作弊:因为您知道输入是整数,舍入和截断会产生相同的结果,您可以使用 lrintf 而不是强制转换或隐式转换为 float 。这应该是对不使用 sse 进行数学运算的 x86 目标的重大改进,尤其是当编译器识别 lrintf 并将其内联时。这是相同的函数,使用 lrintf(x) 而不是 x,添加了 -fno-math-errno 选项(否则 gcc 假设libm 可能想要设置 errno,因此不会替换调用):

f:
        pushl   %eax
        flds    8(%esp)
        fistpl  (%esp)
        movl    (%esp), %eax
        popl    %edx
        ret

请注意,gcc 在编译此函数时做得很糟糕;它可能产生:

f:
        flds    4(%esp)
        fistpl  4(%esp)
        movl    4(%esp), %eax
        ret

这是有效的,因为堆栈上的参数空间属于被调用者并且可以随意破坏。即使不是,movl (%esp),%eax ; popl %edx 当您不关心 edx 中的内容时,这是一种愚蠢的编写 popl %eax...

的方式

关于c - 在 C 中将 float 转换为处理器内部的 int,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16421734/

相关文章:

c# - (type)objectname.var 中的 (type) 是什么

c# - 在运行时转换为特定类型

c++ - c++ 和 c 中的命名空间

python - Pandas => 按组获取第一个和最后一个元素的索引

database - 数据库何时以及如何降低站点速度?

mysql - 从表中选择,其中一列仅包含另一列的元素

Java Map - 整数值转换为字符串

c - 从 Windows 内核模式驱动程序确定文件所有者

c - 使用枚举设置标志时的 AVR C 随机行为

c - Floyd-Warshall 算法最短路径