【问题标题】:Format and arguments inconsistency in printfprintf 中的格式和参数不一致
【发布时间】:2012-05-01 14:12:09
【问题描述】:

对于以下代码:

#include <stdio.h>
int main(){
    printf("%f", 5);
    printf("%d", 5.01);
}

第一个语句将打印 0.000000,第二个语句将打印一个大数字。

我认为 printf 看到格式 %f 会从堆栈中弹出一个 4 字节的参数。然后我查找了一些参考资料,说 printf 函数会将浮点数转换为双精度,因此是 8 字节参数。所以我认为它可能会打印出一个不可预测的值。但是它怎么能打印出0.000000。

第二个也很奇怪。 5.01的二进制格式应该是0 10000001 01000000101000111101100(0x40A051EC),十进制应该是1084248556,但是语句的结果是1889785610,为什么会这样?

【问题讨论】:

标签: c printf


【解决方案1】:

这很令人困惑,但%d 是整数的格式,例如%i(大多数人认为它是双精度的,因为%f 是浮点数,但事实并非如此)。你不能用双精度,你必须使用%f。与%f 相同,不能使用整数;您必须使用浮点数或双精度数。

另外,printf 不会检查你使用它的类型,它只是盲目地将字节解释为你告诉它你给它的类型。使用错误的类型和错误的类型说明符会产生未定义的行为,这就是您看到自己的原因。

【讨论】:

    【解决方案2】:

    在第一种情况下,printf 提取 double(由于 %f),但您传递了 intdouble 的格式与int 的格式不同(请参阅IEEE-754 了解最常用的double 格式)

    第二个类似:printf 期望 int(由于 %d),但你传入了 double

    当你传入不正确的类型时如何解释实际值是未定义的(可能取决于字节序等)

    【讨论】:

    • 在实践中更重要的是,它取决于是否在不相交的寄存器集中传递不同的类型(如 GPR 中的整数/指针(rdi、rsi、rdx...)和向量寄存器中的浮点(xmm0, xmm1, ...))。
    【解决方案3】:

    printf 不是类型安全的,您应该确保为要打印的数据类型使用正确的格式描述符,否则无法保证printf 会产生结果。

    【讨论】:

      猜你喜欢
      • 2020-10-07
      • 2012-04-17
      • 1970-01-01
      • 1970-01-01
      • 2016-05-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多