Gol*_*lum 16 c floating-point printf
我想通过阅读来学习C C程序设计语言,第2版.我有一些编程经验,但没有C.
我目前在第1章.我有以下代码:
float f;
for (f = 0.0; f <= 3; f += 1.1)
printf("A: %3f B: %6.2f\n", f, f + 0.15);
Run Code Online (Sandbox Code Playgroud)
它打印输出:
A: 0.000000 B: 0.15
A: 1.100000 B: 1.25
A: 2.200000 B: 2.35
Run Code Online (Sandbox Code Playgroud)
看起来很好.
现在我按如下方式更改printf:
printf("A: %3d B: %6.2f\n", f, f + 0.15);
Run Code Online (Sandbox Code Playgroud)
新的输出是
A: 0 B: 0.00
A: -1610612736 B: 0.00
A: -1610612736 B: -625777476808257557292155887552002761191109083510753486844893290688350183831589633800863219712.00
Run Code Online (Sandbox Code Playgroud)
这里发生了什么?我希望浮点数转换为int,因为我使用了%d,但事实并非如此.另外,为什么价值B也出错?这里发生了什么事?
Jon*_*ler 17
你打电话的时候:
printf("A: %3d B: %6.2f\n", f, f + 0.15);
Run Code Online (Sandbox Code Playgroud)
C自动将float值转换为double(它是在调用带有可变参数的函数时进行的标准转换,例如int printf(const char *fmt, ...);).为了论证,我们假设它sizeof(int)是4并且sizeof(double)是8(有例外,但它们很少而且很远).
因此,调用已将指针推入堆栈,加上一个8字节的双精度数f,另一个8字节的双精度数f + 0.15.当它处理格式字符串时,%d告诉printf()您int在格式字符串后将4字节压入堆栈.由于这不是你所做的,你已经调用了未定义的行为; 根据C标准,接下来发生的一切都没问题.
然而,最可能的实现轻快地读取4个字节并将它们打印成好像它们int(它相信你说实话).然后它遇到了%6.2f格式; 它将从堆栈中读取8个字节作为a double.有一个外部的可能性,这会导致内存错误导致访问错位(它需要64位机器,要求double在8字节边界上对齐,例如SPARC),否则它将读取4个字节f和从4个字节开始f + 0.15,将它们放在一起以创建一些非常意外的double值 - 如您的示例所示.
无论你告诉它,Printf都会将你指向的记忆对待.没有转换.它将表示float的内存视为int.因为两者的存储方式不同,所以你得到的本质上是一个随机数.
如果要将float输出为整数,则应首先将其转换为:
printf("A: %3d B: %6.2f\n", (int)f, f + 0.15);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
14574 次 |
| 最近记录: |