当前位置:首页  综合精选

综合精选

double c语言输出(double c语言)

2024-09-29 19:16:51
导读 大家好,小东方来为大家解答以上的问题。double c语言输出,double c语言这个很多人还不知道,现在让我们一起来看看吧!1、使用printf时,...

大家好,小东方来为大家解答以上的问题。double c语言输出,double c语言这个很多人还不知道,现在让我们一起来看看吧!

1、使用printf时,它们具有相同的格式说明符,但使用scanf时,它们没有相同的格式说明符。

2、为什么是这样?因为printf的参数被提升,而scanf的参数(作为指针)却不被提升。

3、这种论点提升到底是什么?当较小尺寸的参数(特别是char,short和float)传递给可变参数函数(如printf之类的函数,其参数数量不固定)时,它们将转换为较大尺寸。

4、Char和short转换为int,float转换为double。

5、为什么这样 据我所知,纯粹出于历史原因。

6、C的设计师认为这是个好主意,因为这些转换基本上是免费的,因为所有类型的尺寸都足够小,可以放入单个寄存器或堆栈中的单个“单元”(将内容压入堆栈必须与某些字节边界对齐,例如,堆栈上的每个项目都必须以4的倍数的地址开头。

7、同样,显然,这种转换减少了传递参数时的错误。

8、因此,当您向printf传递float类型的参数时,实际上它会在转换为printf之前就转换为double类型。

9、我们可以使用调试器证明这一点。

10、我写了下面的C代码:主要功能编译成:领取关于C/C++更多学习资料:我在调用printf之前(在地址0x63b处)放了一个断点。

11、根据Linux x86_64调用约定,浮点参数在XMM寄存器中传递(CPU中特殊的小内存位置,可用于对多条数据并行执行同一条指令,但实际上可用于大多数事情) 。

12、因此,我查看了第一个XMM寄存器xmm0,然后:xmm0中的值之一,当解释为双精度值时,是1,恰好是我们传递给printf的值。

13、同时,当将该寄存器中的值解释为浮点数时,它们是这样(巧合的是,我们得到1.875)。

14、因此,转换确实发生了。

15、这就解释了为什么对于printf,我们在浮点数和双精度参数中都使用%f -浮点数无论如何都会转换为双精度,因此printf不能分辨出两者之间的区别。

16、同时,scanf的参数是指针,因此不受此转换的限制。

17、其原因是因为所有指针类型仅包含内存地址,并且所有内存地址都具有相同的大小(在我的64位计算机上为64位)。

18、因此,当scanf在其格式字符串中获得%f时,它将期望一个float *类型的指针,而当它获得%lf时,将期望得到double *类型的指针。

19、如果格式说明符和指针的类型不匹配,则会产生一些有趣的结果。

20、由于float的大小为4个字节,而double的大小为8个字节(至少在我的机器上),因此当我们写入float *类型的指针所指向的位置时,我们将覆盖4个字节的内存。

21、同时,如果我们写入由双*指向的位置,则将覆盖8个字节的内存。

22、考虑以下代码:printf说明符上的.15标志只是使printf精确度更高。

23、由于我们使用的是双精度值(并且正如我刚刚说的那样,%f也适用于printf的双精度值),因此我们实际上可以访问具有这种精度的数字(只要它们不是太大而不能填充即可。

24、我实际上不是对浮点表示非常了解)编译并运行后,结果如下:如您所见,如果我们忽略所有类型的fuckery,则数字应该匹配,但它们甚至不相近。

25、这是为什么?好吧,我们给scanf%f说明符,所以它期望一个浮点数*。

26、但是我们传递了一个双*。

27、现在,这些指针的实际值都只是地址-scanf不知道它们之间的区别。

28、它进行了下去,读取我们输入的值,并将其存储为float 。

29、但是浮点数仅占用4个字节,因此scanf只会在我们可用的double变量的8个字节中写入4个字节。

30、在我的情况下,由于我的机器是低位字节序的,因此似乎对应于double变量的细粒度(小有效位)数字的第4个字节将被覆盖。

31、因此,当我们打印出double double back时,我们得到的数字几乎与以前相同,但最低有效数字有所变化。

32、有想学习更多C/C++知识的,可以点击下方了解更多,领取免费学习资料:。

本文到此分享完毕,希望对大家有所帮助。

免责声明:本文由用户上传,如有侵权请联系删除!