【问题标题】:Why does scanf() need "%lf" for doubles, when printf() is okay with just "%f"?为什么 scanf() 需要 "%lf" 作为双打,而 printf() 只需要 "%f"?
【发布时间】:2010-09-17 15:46:57
【问题描述】:

为什么scanf()在读取double时需要“%lf”中的l,而printf()可以使用“%f”而不管其参数是double还是float?

示例代码:

double d;
scanf("%lf", &d);
printf("%f", d);

【问题讨论】:

  • 我不明白你所说的 POINTER 是什么意思。在 scanf 我们只传递 &variable (i.e)address 所以指针在哪里
  • @deetchanya 在 C 中,当您使用一元 & 运算符“获取”变量的地址时,该操作的结果是指向变量在内存中的存储位置的指针。就是传递给scanf的那个指针。
  • 这是另一篇关于stackoverflow.com/questions/9291348/…的帖子

标签: c scanf length-modifiers


【解决方案1】:

因为对于接受可变参数的函数,C 会将浮点数提升为双精度数。指针不会被提升为任何东西,因此您应该使用 %lf%lg%le(或 C99 中的 %la)来读取双精度。

【讨论】:

    【解决方案2】:

    自 С99 以来,格式说明符和 C 中的浮点参数类型之间的匹配在 printfscanf 之间是一致的。这是

    • %ffloat
    • %lfdouble
    • %Lflong double

    碰巧当float 类型的参数作为可变参数传递时,这些参数会隐式转换为double 类型。这就是为什么在printf 格式说明符%f%lf 是等效且可互换的原因。在printf 中,您可以“交叉使用”%lffloat%fdouble

    但实际上没有理由在实践中这样做。不要使用%fprintf 类型为double 的参数。这是在 C89/90 时代诞生的普遍习惯,但它是一个坏习惯。在printf 中使用%lfdouble 并保留%ffloat 参数保留。

    【讨论】:

    • 我会说在 printf 中使用%f 是一个好习惯,因为这样您的代码总是可以工作,而如果编译器没有符合 C99 的库,则使用 %lf 可能会失败。不幸的是,这种情况确实发生在现实中。
    • 自 С99 以来,格式说明符和 C 中的浮点参数类型之间的匹配在 printfscanf 之间是一致的。 请注意,这并不意味着使用相同的格式说明符意味着[f]printf()写入的数据可以被[f]scanf()读取。通常,对scanf() 使用与printf() 相同的格式说明符将不会成功读取数据。例如,可以由prinf()"%d" 格式说明符插入的空格填充将在scanf() 调用中被相同的"%d" 格式说明符跳过。
    【解决方案3】:

    scanf 需要知道&d 指向的数据的大小才能正确填充它,而可变参数函数将浮点数提升为双精度数(不完全确定为什么),所以printf 总是得到@987654324 @。

    【讨论】:

    • 可变参数函数非常脆弱,因为它需要能够知道传递给它的所有参数的确切类型和大小,并且它不能在编译时强制执行此操作。如果一个变量是错误的类型,则会读取错误的值;如果大小错误,后面的所有变量也会被误读。如果可以传递两种不同大小的float,那么就会引发各种令人讨厌和容易遗漏的问题。
    【解决方案4】:

    因为否则 scanf 会认为您正在传递一个指向浮点的指针,该浮点的大小比双精度小,它会返回一个不正确的值。

    【讨论】:

      【解决方案5】:

      在 C 表达式中使用浮点数或双精度值将导致一个双精度值,因此 printf 无法区分。而指向 double 的指针必须显式地向 scanf 发出信号,这与指向 float 的指针不同,因为指针指向的才是最重要的。

      【讨论】:

      • 浮点数被转换为双精度在这种情况下因为参数是可变长度参数列表的一部分,在 C 中浮点数并不总是被转换为双精度数。
      • 在 C 语言的预标准版本中,float 值在表达式中自动提升为 double。该规则在标准 C 中被放弃。通常,float 在表达式中不会提升为double。当作为可变参数传递时,它只会被提升为double,这就是在这种情况下发生的情况。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-18
      • 1970-01-01
      • 2018-07-30
      • 2011-06-18
      • 2021-04-13
      相关资源
      最近更新 更多