打印浮点值时打印 F 崩溃

printf crashes while printing float values

本文关键字:打印 崩溃      更新时间:2023-10-16

我今天遇到了一个奇怪的问题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()提供的示例代码(。但为什么它最终会崩溃呢?

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

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家族的任何变体都会崩溃。

你的参数'2013, 987/432, 873/65, 983/81'都是整数!

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

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

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

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