为什么我们可以将%d用于scanf和printf?

时间:2014-02-09 03:15:33

标签: c int double printf scanf

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

那么,为什么printf scanf可以使用%d?

这就是我认为的原因是:

浮点(%f)恰好使用64位,而双浮点数(%lf)至少使用32.编译器不知道要为变量分配多少位正在由scanf扫描,因此我们使用%lf告诉编译器它必须至少为32位。

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

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

2 个答案:

答案 0 :(得分:2)

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

除了%ld 之外,它还意味着32位整数。 %lld 也存在,这意味着64位整数。上面的wiki站点很好地解释了所有C数据类型。

答案 1 :(得分: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确实需要知道参数是{em>指针到float还是指向double的指针,因为指针是由默认参数促销。