c - 为什么 gcc 将只读单精度浮点值编译为双精度值?
问题描述
考虑以下示例。(CPU: Intel(R) Core(TM) i7-4790, gcc (GCC) 4.8.5 20150623)
// file test.c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
srand(time(0));
float i = rand();
if (i < 0.042) {
printf("i %f\n", i);
}
}
编译源代码
gcc test.c -O0 -g3
显示反汇编代码
objdump -S a.out
结果出现在这里
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
4005fd: 55 push %rbp
4005fe: 48 89 e5 mov %rsp,%rbp
400601: 48 83 ec 10 sub $0x10,%rsp
srand(time(0));
400605: bf 00 00 00 00 mov $0x0,%edi
40060a: e8 e1 fe ff ff callq 4004f0 <time@plt>
40060f: 89 c7 mov %eax,%edi
400611: e8 ba fe ff ff callq 4004d0 <srand@plt>
float i = (float)rand() / (float)(RAND_MAX);
400616: e8 e5 fe ff ff callq 400500 <rand@plt>
40061b: f3 0f 2a c0 cvtsi2ss %eax,%xmm0
40061f: f3 0f 10 0d d1 00 00 movss 0xd1(%rip),%xmm1 # 4006f8 <__dso_handle+0x10>
400626: 00
400627: f3 0f 5e c1 divss %xmm1,%xmm0
40062b: f3 0f 11 45 fc movss %xmm0,-0x4(%rbp)
if (i < 0.042) {
400630: f3 0f 10 45 fc movss -0x4(%rbp),%xmm0
400635: 0f 5a c0 cvtps2pd %xmm0,%xmm0
400638: f2 0f 10 0d c0 00 00 movsd 0xc0(%rip),%xmm1 # 400700 <__dso_handle+0x18>
40063f: 00
400640: 66 0f 2e c8 ucomisd %xmm0,%xmm1
400644: 76 17 jbe 40065d <main+0x60>
printf("i %f\n", i);
400646: f3 0f 10 45 fc movss -0x4(%rbp),%xmm0
40064b: 0f 5a c0 cvtps2pd %xmm0,%xmm0
40064e: bf f0 06 40 00 mov $0x4006f0,%edi
400653: b8 01 00 00 00 mov $0x1,%eax
400658: e8 53 fe ff ff callq 4004b0 <printf@plt>
}
}
我发现它从一个双精度值中读取了 0.042,然后将“i”转换为一个双精度值,然后进行比较。为什么它不只加载一个单精度(0.042)值并进行比较?(我认为这可能会带来更好的性能),如果我想强迫它这样做,我该怎么办?
解决方案
没有后缀的浮点文字是 a double
,所以0.042
是双精度数。以同样的方式,int
当它的值可以由 ashort
或 a 支持时,整数文字是 a char
。
如果你想float
使用后缀f或F
推荐阅读
- redis - Redis,从命令行配置 redis.conf
- sql - 用于重命名 SQL Server XML 中的元素的函数
- c - 不能在可变二维数组中使用 scanf
- c# - 将 lambda 函数作为参数传递并在方法体中给出其参数
- ruby-on-rails - form_for 嵌套属性:创建不保存到数据库
- python - 未知速记标志:-E 中的“E”
- c# - 尝试将图像链接作为字符串传递给 POST 网络请求以发送到 API
- json - 在 SQL Server 2016 中使用 JSON 的两列字符串聚合
- output - 为什么随机森林从相同的输入生成不同的输出
- db2 - 在 Function 中使用 Unpivot