c语言的printf输出浮点数的一些问题

在printf时:如果以%f格式输出,将输出8个字节(scanf输入时,%f是4个字节)

在参数入栈时如果是float型或者double型 直接入栈8个字节,此时输出及后续输出都没问题

但如果参数小于8个字节且不是float型:比如int   shor int  ,就会扩展符号位,成为4个字节再入栈,但是输出的是8个字节,所以会读取其他参数的入栈结果

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, const char *argv[])
{
    int a = 3;
    int b = 5;
    printf("%f %d\n", a, b);
    return 0;
}

在linux下的gcc输出结果是:  0.000000    134513801      -->后面这个值是一个无用值,比如int x;  printf("%d\n", x)  -->输出的就是:134513801

在vs2013下的输出结果是:0.000000   0     vs中对int x; printf("%d\n",x)会出现错误,因为x未初始化,

-->上述入栈结果是(十六进制):

栈顶                                 栈底

03 00 00 00    05 00 00 00

-->%f 读取8个字节,直接把b的入栈结果读走了

  符号位  阶码  尾数  总位数

  短浮点数   1    8   23   32

  长浮点数   1    11   52   64

在32位浮点数的读取中:从内存中读出0x 03 00 00 00后,因为是小端模式,所以变成0x 00 00 00 03

0   000 0000 0  000 0000 0000 0000 0000 0011

第一个0是符号位:表正

第2到9位是阶码,32位浮点数的指数偏移量是127, 所以此处是-127

后面的均为小数点后面的:小数点前为1

-->(1 + 2^(-22) + 2^(-23)) * 2^(-127)

趋近于0;

在64位浮点数中:则阶码偏移量为:2^(10) - 1

例1:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, const char *argv[])
{
    int a = 3;
    int b = 0xffffffff;
    printf("%f %d\n", a, b);
    return 0;
}

在gcc中结果为:-nan    134513801     -->-nan表示负无穷大

在VS2013中结果为:-1.#QNAN0   0

printf的栈中: 03 00 00 00 ff ff ff ff

-->按%f读取的时候:ff ff ff ff 00 00 00 03

-->按浮点数解析相应的位!

例2:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, const char *argv[])
{
    int a = 0x10000003;
    int b = 0x40110000;
    printf("%f %d\n", a, b);

    int c[2];
    c[0] = 0x10000003;
    c[1] = 0x40110000;
     double d = *(double*)c;
     printf("%f\n", d);
    return 0;
}

gcc中:

分析:

在第一个printf的栈中:  03 00 00 10 00 00 11 40

-->以%f读出时出栈结果:0x 40 11 00 00 10 00 00 03

-->64位浮点数解析:0100 0000 0001 0001 0000 0000 0000 0000 0001 0000 0000 0000 0000 0000 0000 0011

符号位:0

阶码:100 0000 0001    -->11位  -->减去偏移量:2^(10) -1  -->结果为2

小数位:0001 0000 0000 0000 0000 00....

最后大小:(1 + 2^(-4) + 2^(-52) + 2^(-51) + 2^(-24)) * 2^(2)

-->2进制:100 + 2^(-2)   -->4.250000

例3:

反过来看

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, const char *argv[])
{
    int a = 5;
    float b = 3.0;
    printf("%d %d\n" , a, b);
    return 0;
}

输出结果: 5   0

b虽然是4个字节的float型,但是在入栈时会变换为8个字节的fdouble型

--->float型的3.0的表示:0x 40 40 00 00

-->内存中: 00 00 40 40

-->printf输出时入栈变为扩展8个字节的double型: 00 00 00 00 00 00 08 40

-->此时printf的栈中:

05 00 00 00  00 00 00 00 00 00 08 40

-->以%d格式输出两次: 5   0

32位的float型的3二进制码:   0 100 0000 0 100  0000 0000 0000 0000 0000

64位的double型3的二进制:   0 100 0000 0000  1000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000

对比:                   32                    64

符号位                    0                     0

阶码:                100 0000 0       100 0000 0000    -->64位在32位后面添加了3个0

尾数 :               100.....               100....                   -->64位在32位后面添加了29个0

总结:

printf 以%f格式输出时输出8个字节,float类型输出时入printf的栈要扩展为double型的8个字节!

printf的返回值为实际控制输出的字符数(不包括字符串末尾的‘\0‘),



时间: 2024-10-02 08:44:10

c语言的printf输出浮点数的一些问题的相关文章

c语言:用getchar函数读入两个字符给c1,c2,用putchar和printf输出。思考问题

用getchar函数读入两个字符给c1,c2,分别用putchar和printf输出这两个字符.思考以下问题: (1)变量c1和c2定义为字符型还是整型?或二者皆可? (2)要求输出c1和c2的ASCII码,应如何处理? (3)整形变量和字符变量是否在任何情况下都可以互相代替?char c1, c2;和int  c1, c2;是否无条件等价? 程序: #include<stdio.h> int main() { char c1, c2; printf("请输入两个字符c1,c2:&q

[转载] c++ cout 格式化输出浮点数、整数及格方法

C语言里可以用printf(),%f来实现浮点数的格式化输出,用cout呢...? 下面的方法是在网上找到的,如果各位有别的办法谢谢留下... iomanip.h是I/O流控制头文件,就像C里面的格式化输出一样.以下是一些常的: dec 置基数为10 相当于"%d" hex 置基数为16 相当于"%X" oct 置基数为8 相当于"%o" setfill(c) 设填充字符为c setprecision(n) 设显示小数精度为n位 setw(n)

C语言的printf输出格式控制

printf大家都耳熟能详,但是能真正将其用法弄透的估计很少见. 转一篇,改天整理. 1.转换说明符 %a(%A)     浮点数.十六进制数字和p-(P-)记数法(C99) %c         字符 %d         有符号十进制整数 %f         浮点数(包括float和doulbe) %e(%E)     浮点数指数输出[e-(E-)记数法] %g(%G)     浮点数不显无意义的零"0" %i         有符号十进制整数(与%d相同) %u        

黑 马 程 序 员_视频学习总结&lt;c语言&gt;----02 printf和scanf函数、基本语句和运算、流程控制、函数、数组、字符串

---------------------- ASP.Net+Unity开发..Net培训.期待与您交流! ---------------------- 一.printf函数 1.在使用peintf函数前必须加入#include <stdio.h>,使用它可以向标准输出设备(比如屏幕)输出数据,其中使用格式是 printf(“字符串”) :或者 printf(“字符串”, 格式符参数): 2.常用的格式符及其含义如图所示 3.格式符还可以添加输出宽度 二.scanf函数 1.在使用scanf函

1.1编程基础之输入输出-07:输出浮点数

07:输出浮点数 #include<stdio.h> int main() { double i; scanf("%lf",&i); printf("%f\n",i); printf("%.5f\n",i); printf("%e\n",i); printf("%g\n",i); return 0; } 总时间限制:  1000ms 内存限制:  65536kB 描述 读入一个双精度浮点

【C语言模拟实现】浮点数-转-定点数

要想超神,就要什么都精! 知识准备: 1. 输出浮点数的十六进制形式?(利用指针输出) 将浮点数指针-转换成-整型指针,以十六进制的格式输出指针内容. 示例程序: #include<stdio.h> int main() { float *var; scanf("%f",var); printf("%x",*((int*)var)); } 测试: 输入(float) 输出(十六进制) 二进制 8.25 41040000 0100 0001 0000 01

//%f表示以十进制格式化输出浮点数 %.2f

//%f表示以十进制格式化输出浮点数 String s1 ="评分: %.1f"; String s2 = String.format(s1, 8.0); System.out.println(s2); System.out.printf("%s%n", new Integer(1212)); // %n表示换行 System.out.printf("%s%n", "end line"); // 还能够支持多个參数 Syste

[转]C语言文件输入/输出ACM改进版(freopen函数)

C语言文件输入/输出ACM改进版(freopen函数) 2009年5月27日 10:379,457 浏览数发表评论阅读评论 文章作者:姜南(Slyar) 文章来源:Slyar Home (www.slyar.com) 转载请注明,谢谢合作. 昨天发了一篇<C语言 使用文件输入/输出数据>,使用的是最普通的文件输入/输出方法,Felix大牛随后给了一种更简单的改进方法,在ACM中应用很广,而且超赞,现在来介绍一下. 这次用到的文件打开函数不再是fopen,而是stdio.h中包含的另一个函数fr

printf输出各种类型,cout控制输出各式

1 int a = 10; 2 char c = 'A'; 3 int *p = &a; 4 char *st = "ahj"; 5 float x = 3.1415926; 6 cout << &a << endl; 7 printf("%d,%x,%o,%d,%p,%s,%f", a, a,a, c,p,++st,x); 8 %d 输出10进制整数 %x 输出十六进制(不输出前缀0x) %o 输出八进制 %c 输出字符,用