繁体   English   中英

printf在打印浮点值时崩溃

[英]printf crashes while printing float values

今天我遇到了一个与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()也崩溃了(是的,我尝试使用上面的参数为vsnprintf()提供了FormatOutput示例代码)。 但为什么最终会崩溃呢?

你答应打印double s但是你传入int s: 987/432是一个int 例如,如果您希望此值为double ,则使用987.0/432

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

无需使用(double)873/(double)65进行铸造,只需使用(double)873/65甚至873.0/65 int除以int将始终产生int值。 要打印double ,您可以使用987.0/432或简单地使用987f/432来打印float 两者都有效。

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

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

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

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 ),现在已经超出界限了! 你的第二个例子并没有在那里崩溃,这可能是运气。 到达%sprintf()会查找指针...如果它没有从越界访问中崩溃,它将尝试访问结果指针的无效内存地址。

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM