为什么 gcc 将只读单精度浮点值编译为双精度值?
why gcc compile readonly single-precision floating-point value as the double-precision one?
考虑以下示例。 (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 [=13=]x10,%rsp
srand(time(0));
400605: bf 00 00 00 00 mov [=13=]x0,%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 [=13=]x4006f0,%edi
400653: b8 01 00 00 00 mov [=13=]x1,%eax
400658: e8 53 fe ff ff callq 4004b0 <printf@plt>
}
}
我发现它从一个双精度值中读出0.042,然后将"i"转换为一个双精度值,然后进行比较。为什么它不加载单精度(0.042)值并进行比较? (我认为这可能会带来更好的性能),如果我想强制它这样做,我应该怎么做?
没有后缀的浮点文字是 double
,所以 0.042
是双精度数。以同样的方式,整数文字是 int
当它的值可以由 short
或 char
.
支持时
如果你想要 float
使用后缀 f 或 F
考虑以下示例。 (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 [=13=]x10,%rsp
srand(time(0));
400605: bf 00 00 00 00 mov [=13=]x0,%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 [=13=]x4006f0,%edi
400653: b8 01 00 00 00 mov [=13=]x1,%eax
400658: e8 53 fe ff ff callq 4004b0 <printf@plt>
}
}
我发现它从一个双精度值中读出0.042,然后将"i"转换为一个双精度值,然后进行比较。为什么它不加载单精度(0.042)值并进行比较? (我认为这可能会带来更好的性能),如果我想强制它这样做,我应该怎么做?
没有后缀的浮点文字是 double
,所以 0.042
是双精度数。以同样的方式,整数文字是 int
当它的值可以由 short
或 char
.
如果你想要 float
使用后缀 f 或 F