浮点型数值强转成整型时,发生了什么?

您所在的位置:网站首页 强制float转换int 浮点型数值强转成整型时,发生了什么?

浮点型数值强转成整型时,发生了什么?

2024-02-28 04:12| 来源: 网络整理| 查看: 265

背景

数值的类型强转和指针的类型强转是不一样的,前者会改变数据的内容,后者只会改变数据的解释方式。

解析 示例

定义浮点数1.5,强转成int时会截断成1,而以*(int *)解释其内容时会解释成1069547520

示例代码:

#include float a = 1.5; int *b = &a; int main() { printf("a == %f\n", a); printf("&a == %p\n", &a); printf("(int)a == %d\n", (int)a); printf("b == %p\n", b); printf("*b == %d\n", *b); return 0; }

编译:

wanghaipeng@v03p:~/demo$ gcc float_to_int.c float_to_int.c:4:10: warning: initialization from incompatible pointer type [-Wincompatible-pointer-types] int *b = &a; ^

运行:

a == 1.500000 &a == 0x5593b7253010 (int)a == 1 b == 0x5593b7253010 *b == 1069547520 数值强转时底层发生了什么?

数值强转需要CPU硬件的支持,对于X86-64,示例代码的main()反汇编:

printf("a == %f\n", a);打印前cvtss2sd指令将a扩展成double 000000000000065a : 65a: 55 push %rbp 65b: 48 89 e5 mov %rsp,%rbp 65e: f3 0f 10 05 aa 09 20 movss 0x2009aa(%rip),%xmm0 # 201010 665: 00 666: f3 0f 5a c0 cvtss2sd %xmm0,%xmm0 66a: 48 8d 3d 03 01 00 00 lea 0x103(%rip),%rdi # 774 671: b8 01 00 00 00 mov $0x1,%eax 676: e8 b5 fe ff ff callq 530 printf("&a == %p\n", &a);不涉及数值强转 67b: 48 8d 35 8e 09 20 00 lea 0x20098e(%rip),%rsi # 201010 682: 48 8d 3d f4 00 00 00 lea 0xf4(%rip),%rdi # 77d 689: b8 00 00 00 00 mov $0x0,%eax 68e: e8 9d fe ff ff callq 530 printf("(int)a == %d\n", (int)a);打印前cvttss2si指令将a截断成int,存放到eax寄存器 693: f3 0f 10 05 75 09 20 movss 0x200975(%rip),%xmm0 # 201010 69a: 00 69b: f3 0f 2c c0 cvttss2si %xmm0,%eax 69f: 89 c6 mov %eax,%esi 6a1: 48 8d 3d df 00 00 00 lea 0xdf(%rip),%rdi # 787 6a8: b8 00 00 00 00 mov $0x0,%eax 6ad: e8 7e fe ff ff callq 530 printf("b == %p\n", b);不涉及数值强转 6b2: 48 8b 05 5f 09 20 00 mov 0x20095f(%rip),%rax # 201018 6b9: 48 89 c6 mov %rax,%rsi 6bc: 48 8d 3d d2 00 00 00 lea 0xd2(%rip),%rdi # 795 6c3: b8 00 00 00 00 mov $0x0,%eax 6c8: e8 63 fe ff ff callq 530 printf("*b == %d\n", *b);不涉及数值强转,仅更改解释方式 6cd: 48 8b 05 44 09 20 00 mov 0x200944(%rip),%rax # 201018 6d4: 8b 00 mov (%rax),%eax 6d6: 89 c6 mov %eax,%esi 6d8: 48 8d 3d bf 00 00 00 lea 0xbf(%rip),%rdi # 79e 6df: b8 00 00 00 00 mov $0x0,%eax 6e4: e8 47 fe ff ff callq 530 6e9: b8 00 00 00 00 mov $0x0,%eax 6ee: 5d pop %rbp 6ef: c3 retq 结论

对于x86-64平台,实现float到int强转的指令是cvttss2si 浮点值截断指令

总结

当我们将值类型强转时,必定有对应的CPU指令实现,不要以为没有开销。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3