关于整形和浮点型的格式输出

一个很好玩的现象:

源代码:

#include <stdio.h>

int main()
{
        int a = 10000;
        float b = 55.55;
        int c = 9988;

        printf("a : %f 
",a);
        printf("c : %f 
",c);
        printf("b : %d 
",(int)b);
        printf("a : %f 
",a);
        printf("c : %f 
",c);
        printf("b : %f 
",b);
        printf("a : %f 
",a);
        printf("c : %f 
",c);
        printf("b : %d 
",b);

        return 0;
}

输出:

root@Ivy-debian-64:/home/zhangxu# ./a.out
a : 0.000000
c : 0.000000
b : 55
a : 0.000000
c : 0.000000
b : 55.549999
a : 55.549999
c : 55.549999
b : -1645481984
root@Ivy-debian-64:/home/zhangxu# ./a.out
a : 0.000000
c : 0.000000
b : 55
a : 0.000000
c : 0.000000
b : 55.549999
a : 55.549999
c : 55.549999
b : 1511591936

结果很奇怪,注意a、b以同样的格式输出时的不同结果。

 1     .file   "double_int.c"
 2         .section        .rodata
 3 .LC1:
 4         .string "a : %f 
"
 5 .LC2:
 6         .string "c : %f 
"
 7 .LC3:
 8         .string "b : %d 
"
 9 .LC4:
10         .string "b : %f 
"
11         .text
12         .globl  main
13         .type   main, @function
14 main:
15 .LFB0:
16         .cfi_startproc
17         pushq   %rbp
18         .cfi_def_cfa_offset 16
19         .cfi_offset 6, -16
20         movq    %rsp, %rbp
21         .cfi_def_cfa_register 6
22         subq    $16, %rsp
23         movl    $10000, -4(%rbp)
24         movl    .LC0(%rip), %eax
25         movl    %eax, -8(%rbp)
26         movl    $9988, -12(%rbp)
27         movl    -4(%rbp), %eax
28         movl    %eax, %esi               //参数 %esi = 10000
29         movl    $.LC1, %edi              //格式串 %edi
30         movl    $0, %eax                 //0代表参数为整型 %eax (只是猜测,含义上不明确)
31         call    printf                   //输出 0.000000 
32 
33         movl    -12(%rbp), %eax
34         movl    %eax, %esi
35         movl    $.LC2, %edi
36         movl    $0, %eax
37         call    printf                    //同上
38 
39         movss   -8(%rbp), %xmm0           //单精度浮点数移动指令
40         cvttss2si       %xmm0, %eax       //单精度浮点数转换成整型,带截断,装入%eax  
41         movl    %eax, %esi                //参数 %esi = 55
42         movl    $.LC3, %edi           
43         movl    $0, %eax
44         call    printf
45 
46         movl    -4(%rbp), %eax
47         movl    %eax, %esi
48         movl    $.LC1, %edi
49         movl    $0, %eax
50         call    printf                    //xmm0中没有值,依然输出0.000000
51 movl -12(%rbp), %eax 52 movl %eax, %esi 53 movl $.LC2, %edi 54 movl $0, %eax 55 call printf //同 line 50 56 57 movss -8(%rbp), %xmm0 58 cvtps2pd %xmm0, %xmm0 //单精度转换成双精度,装入xmm0 59 movl $.LC4, %edi //格式串 60 movl $1, %eax //1代表参数为浮点型 %eax 61 call printf //输出55.549999 62 63 movl -4(%rbp), %eax 64 movl %eax, %esi 65 movl $.LC1, %edi 66 movl $0, %eax 67 call printf //输出55.549999 68 69 movl -12(%rbp), %eax 70 movl %eax, %esi 71 movl $.LC2, %edi 72 movl $0, %eax 73 call printf //输出55.549999 74 75 movss -8(%rbp), %xmm0 76 cvtps2pd %xmm0, %xmm0
#      movl $5555, %esi
77 movl $.LC3, %edi 78 movl $1, %eax 79 call printf //输出任意值 80 81 movl $0, %eax 82 leave 83 .cfi_def_cfa 7, 8 84 ret 85 .cfi_endproc 86 .LFE0: 87 .size main, .-main 88 .section .rodata 89 .align 4 90 .LC0: 91 .long 1113469747 92 .ident "GCC: (Debian 4.7.2-5) 4.7.2" 93 .section .note.GNU-stack,"",@progbits

可能的原因如下,

如果格式串中有“%f”时,printf就会从xmm中读出相应的值,所以如果xmm中没有正确的值,就会输出0.000000。如果有,就会用此时xmm中的值,当成输入,这就是line 56、line 73输出55.549999(精度问题,如果是双精度浮点会输出55.550000)的原因。因为之前用“%f”输出b的时候,将xmm赋值了。

如果格式串中有“%d”时,printf就从esi中读取相应的值,所以line 79会输出任意值,因为此时esi的值可能是任意的。如果在line 76和 line 77之间人为地给esi赋值为5555,就会输出b:5555。

单精度和双精度的情况不同。

参考:

http://scc.qibebt.cas.cn/docs/optimization/VTune(TM)%20User's%20Guide/mergedProjects/analyzer_ec/mergedProjects/reference_olh/instruct32_hh/vc203.htm

http://scc.qibebt.cas.cn/docs/optimization/VTune(TM)%20User's%20Guide/mergedProjects/analyzer_ec/mergedProjects/reference_olh/instruct32_hh/vc55.htm

http://scc.qibebt.cas.cn/docs/optimization/VTune(TM)%20User's%20Guide/mergedProjects/analyzer_ec/mergedProjects/reference_olh/instruct32_hh/vc68.htm

http://scc.qibebt.cas.cn/docs/optimization/VTune(TM)%20User's%20Guide/mergedProjects/analyzer_ec/mergedProjects/reference_olh/instruct32_hh/vc202.htm

 
原文地址:https://www.cnblogs.com/godjesse/p/3329260.html