3

我今天遇到了一个奇怪的问题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()但是为什么最终会崩溃呢?

4

5 回答 5

6

你答应打印doubles 但你传入ints: 987/432is an int. 例如,如果您希望此值成为double您将使用987.0/432的 。

于 2013-09-02T19:54:22.080 回答
2

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

于 2013-09-02T19:59:50.620 回答
2

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

于 2013-09-02T20:06:19.647 回答
2

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

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

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

于 2013-09-02T20:11:03.607 回答
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-bit double!因此,它读取987/432873/65- 的组合内存空间,给出垃圾结果。之后,另一个 64 位double:983/81和指向"Some..."- 垃圾的指针再次出现。

接下来是另一个 64 位双精度(第三个%f),现在超出了范围!您的第二个示例没有在那里崩溃可能是幸运的。当它到达时%sprintf()会寻找一个指针......如果它没有因越界访问而崩溃,它将试图访问结果指针的无效内存地址。

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

  2. 家庭的任何变化printf都会同样崩溃。

于 2013-09-02T23:09:39.083 回答