`printf()`如何区分浮点参数和整数类型参数?

时间:2018-02-24 14:36:07

标签: c floating-point printf

如果我有

printf("%f\n", 3);

我得到了

3.000000

如果我有:

printf("%f\n", 3.0);

我得到了同样的答案。

但是这就是事情,3和3.0应该是完全不同的,有点明智。

3.0应该类似于01000000010000000000000000000000(但由于vararg函数中的隐式转换,因此是双精度) 3应该是00000000000000000000000000000011

3必须以某种方式转换为浮动才能显示。

所以我的问题是,这是怎么做到的?编译器是否以某种方式作弊?我如何在我自己的变量args函数中实现它?

2 个答案:

答案 0 :(得分:2)

如果您的源代码包含printf("%f\n", 3);且结果输出为“3”,那么最有可能发生的是:

  • 程序中的其他位置有一个浮点3,例如x = 3.;之类的赋值语句或printf等其他printf("%f\n", 3.0);调用。
  • 为了使用它3,编译器将其加载到浮点寄存器中。它可能是针对printf之前的代码执行此操作,也可能是为printf之后的代码做准备。
  • 当评估printf("%f\n", 3);时,该浮点3位于寄存器中,当使用double转换说明符调用printf时,应该是%f参数
  • 因此,由于用于传递%f参数的寄存器恰好有一个浮点3,printf使用该值并产生“3”的结果。

换句话说,你的程序很大程度上是通过偶然而非设计来“工作”的。事实上你确实错误地调用了printf,它只产生了“3”,因为不相关的因素恰好发生了。如果该浮点寄存器中的值为5或-3.25,则printf将打印该值。

printf例程无法确定传递它的值的类型。 (好的编译器会在编译时检查类型,如果格式字符串是文字[而不是在运行时计算的东西]。但这是由编译器查看调用的源代码而不是{ {1}}常规本身。)

答案 1 :(得分:0)

How does printf() distinguish between floating point arguments and integer type arguments?

printf() relies on the calling code to to pass objects of the expected type.


printf() analyzes the format string, which in this case is "%f\n".

The "%f" steers code to expect that the next parameter is a double.

If a float is passed, it is converted to a double as part of the usual conversion of arguments to the ... part of a function.

With a float/double passed by the calling code, printf() will properly get that data as a double and print it. If the calling code passed some other type, the result is undefined behavior (UB). This UB is well explain by @Eric Postpischil.

how is this done? Does the compiler cheat somehow?

How would I implement this in my own variable args function?

The unexpected undefined behavior seen by OP is not certainly reproducible with user code.