【问题标题】:Why can we use %d for both scanf and printf?为什么我们可以将 %d 用于 scanf 和 printf?
【发布时间】:2014-03-06 11:04:48
【问题描述】:

scanf needs %lf for doubles and printf is okay with just %f

那么,为什么printf scanf 可以接受 %d?

这就是我认为的原因:

浮点 (%f) 正好使用 64 位,而双浮点数 (%lf) 至少使用 32。编译器不知道要为正在扫描的变量分配多少位由scanf 输入,所以我们使用%lf 告诉编译器它需要至少为32 位。

好的...但是为什么我们将%d 用于scanfprintf?为什么不%ld%d?对于初学者来说,%ld 在 C 中不存在。 %d 是一个有符号十进制数,至少需要 16 位。您已经告诉编译器分配给它的位数的下限是多少,所以对于scanf 来说没问题。这也是我们没有%ld 的原因。

如果我错了,请纠正我或告诉我我可以做些什么来使这个答案更好。我很确定这不是一个完美的答案。

【问题讨论】:

  • 编译器不必对 %x 做任何事情。总而言之,printfscanf 是库函数,它们解释格式字符串并使用指定格式从/到已分配的内存复制到 stdin/from stdout...
  • 浮点数使用 64 位,但双浮点数使用 32 ...?你确定吗?
  • 对于long %ldlong long %lldshort %hd
  • @XTian,是的,我想我错了。谢谢你。来自维基百科:“双精度浮点 (%lf) 格式是一种计算机数字格式,在计算机内存中占用 8 个字节(64 位),并通过使用浮点表示广泛的动态值范围。” - en.wikipedia.org/wiki/Double_precision_floating-point_format

标签: c int double printf scanf


【解决方案1】:

请参阅 C99 标准中的 §6.5.2.2/6-7。

§6.5.2.2/6 定义了默认参数提升:(添加了重点)

对每个参数执行整数提升,float 类型的参数被提升为double

并指定这些提升是在没有原型声明的函数的参数上执行的(即,使用空参数列表() 而不是(void),后者用于表示没有参数)。

第 7 段还指定如果函数的原型有一个尾随省略号 (...):

函数原型声明器中的省略号符号导致参数类型转换在最后一个声明的参数之后停止。默认参数提升是在尾随参数上执行的。

整数提升在 §6.3.1.1/2 中定义;他们适用于

  • “整数转换等级小于或等于intunsigned int等级”的整数类型的对象或表达式:粗略地说,任何更小的整数类型,例如布尔或字符类型;

  • _Boolintsigned intunsigned int 类型的位域。

如果int 可以表示原始类型的所有值(受宽度限制,对于位域),则该值将转换为int;否则,它将转换为unsigned int。这些称为整数促销。

整数提升不会改变所有其他类型。

简而言之,如果你有 varargs 函数,比如printfscanf

  • 不大于int 的整数参数将转换为(可能是无符号的)int。 (这不包括long。)

  • 不大于double 的浮点参数将转换为double。 (这包括float。)

  • 指针不变。

  • 其他非指针类型不变。

所以printf 不需要区分floatdouble,因为它永远不会传递float。它确实需要区分intlong

scanf 确实需要知道参数是指针 指向float 还是指向double 的指针,因为默认参数提升不会改变指针。

【讨论】:

  • 我的总结很简单,C 会一直将浮点数 (%f) 提升为双精度数 (%lf),但 16 位整数 (%d) 仅在 int 不能转换为无符号整数时表示原始类型的所有值。因此,scanf 可以接受 %d,但不能接受 %f。它是否正确?我想知道我最终是否正确。
  • @DirkHaupt 不,这是不正确的。首先,scanf 可以接受%fint (%d) 也不一定是 16 位的,所以这无关紧要。 scanfprintf 之间的区别在于scanf 参数是指针printf(数字)参数是。价值受标准促销的影响。指针不是,因为您不能神奇地将指向的内容更改为不同的格式。因此,如果您将float 传递给printf,它将在printf 看到它之前被提升为double。但是如果你将pointer to float 传递给scanfscanf 需要知道这一点。
【解决方案2】:

您可以将 scanf 视为将输入流转换为代码中定义的变量。因此,scanf 需要知道每个变量的确切大小。一般来说,the 32-bit and 64-bit IEEE 754 binary floating-point formats are used 在 C 中。所以,%f 表示 32 位,%lf 表示 64 位。

除了 %ld 存在,它表示 32 位整数。 %lld 也存在,表示 64 位整数。上面的 wiki 站点很好地解释了所有 C 数据类型。

【讨论】:

    猜你喜欢
    • 2020-12-28
    • 1970-01-01
    • 2012-06-03
    • 2014-05-30
    • 1970-01-01
    • 2021-11-09
    • 1970-01-01
    • 2021-05-09
    • 1970-01-01
    相关资源
    最近更新 更多