printf在打印浮点值时崩溃

时间:2013-09-02 19:51:55

标签: c++ c printf

今天我遇到了printf()的奇怪问题。但即使经过分析,我也找不到它的答案。因此在这里分享。我尝试了这三个printf()语句:

printf("\nValue of this division is %f", (double)873/(double)65);

按预期打印正确的输出。

printf("\nSome message with an integer here %d followed by floats %f, %f, %f", 2013, 987/432, 873/65, 983/81);

给我错误的值(因为我没有把它们加成双倍?)

printf("\nSome message with an integer here %d followed by floats %f, %f, %f and now string at end: %s", 2013, 987/432, 873/65, 983/81, "Some trial string here");

printf()在这里坠毁了!这引起了两个问题:

  1. 我在MSDN中看到了“FormatOutput(LPCSTR formatstring,...)”示例,其中它们分配了固定宽度的目标缓冲区,然后用它调用vsnprintf()。我相信printf()在同一条线上工作。但我没有找到printf()的任何内部缓冲区大小。如果它动态分配内存,那么它如何计算缓冲区大小?

  2. printf()在上一行崩溃,因为vsnprintf()也在那里崩溃(是的,我尝试使用上述参数为FormatOutput提供vsnprintf()示例代码。但为什么最终会崩溃?

5 个答案:

答案 0 :(得分:6)

您承诺打印double但是您传递int s:987/432int。例如,如果您希望此值为double,则可以使用987.0/432

答案 1 :(得分:2)

你的论点`2013,987 / 438,873 / 65,983 / 81'都是整齐的!

答案 2 :(得分:2)

无需使用(double)873/(double)65进行投射,只需使用(double)873/65甚至873.0/65即可。将int除以int将始终生成int值。要打印double,您可以使用987.0/432或仅987f/432打印float。两者都有效。

答案 3 :(得分:2)

在您的示例中,当它需要双精度浮点时,您将整数除法的结果提供给printf (...)。使用单精度或双精度浮点除法或更正格式字符串。请注意,单精度浮点是automatically promoted到双精度,就像char和short在与变量参数列表一起使用时被提升为int。

作为一个思想实验,你应该考虑在一个假设的场景中发生可能的无数事情,在这个场景中你将指针从32位数据类型转换为64位类型,然后尝试取消引用它。就像在上面说明的指针场景中一样,由于不正确地传递数据类型,您正在处理未定义的行为。如果调用未定义的行为,可能会发生许多令人讨厌的事情并导致程序崩溃。

尽管如此,一些编译器能够在编译时解析您的格式字符串,并根据您提供的参数列表printf (...)验证它。您可能希望查看系统上可用的编译器警告,以便将来可以避免这种情况。

答案 4 :(得分:2)

printf("\nSome message with an integer here %d followed by floats %f, %f, %f and now string at end: %s", 2013, 987/432, 873/65, 983/81, "Some trial string here");

如前面的答案所解释的,整数除法的结果是整数。因此,987/432会在您的系统上产生(最有可能) 32位int。但%f告诉printf期待64位double!因此,它读取987/432873/65的组合内存空间 - 给出垃圾结果。然后,另一个64位double983/81和指向"Some..."的指针 - 再次出现垃圾。

接下来是另一个64位双(第三个%f),现在已超出界限!你的第二个例子并没有在那里崩溃,这可能是运气。到达%s时,printf()将寻找指针...如果它没有从越界访问中崩溃,它将尝试访问结果指针的无效内存地址

  1. printf()不需要分配内存。它直接写入标准输出(例如终端窗口)

  2. printf系列的任何变体都会崩溃。