今天我遇到了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()
也在那里崩溃(是的,我尝试使用上述参数为FormatOutput
提供vsnprintf()
示例代码。但为什么最终会崩溃?
答案 0 :(得分:6)
您承诺打印double
但是您传递int
s:987/432
是int
。例如,如果您希望此值为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/432
和873/65
的组合内存空间 - 给出垃圾结果。然后,另一个64位double
:983/81
和指向"Some..."
的指针 - 再次出现垃圾。
接下来是另一个64位双(第三个%f
),现在已超出界限!你的第二个例子并没有在那里崩溃,这可能是运气。到达%s
时,printf()
将寻找指针...如果它没有从越界访问中崩溃,它将尝试访问结果指针的无效内存地址
printf()
不需要分配内存。它直接写入标准输出(例如终端窗口)
printf
系列的任何变体都会崩溃。