[英]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()
在这里崩溃了! 这引起了两个问题:
我在MSDN中看到了“FormatOutput(LPCSTR formatstring,...)”示例,其中它们分配了固定宽度的目标缓冲区,然后用它调用vsnprintf()
。 我相信printf()
在同一行上工作。 但我没有找到printf()
任何内部缓冲区大小。 如果它动态分配内存,那么它如何计算缓冲区大小?
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/432
和873/65
的组合内存空间 - 给出垃圾结果。 然后,另一个64位double
: 983/81
和指向"Some..."
指针 - 再次出现垃圾。
接着是另一个64位双(第三个%f
),现在已经超出界限了! 你的第二个例子并没有在那里崩溃,这可能是运气。 到达%s
, printf()
会查找指针...如果它没有从越界访问中崩溃,它将尝试访问结果指针的无效内存地址。
printf()
不需要分配内存。 它直接写入标准输出(例如终端窗口)
printf
系列的任何变化都会崩溃。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.