scanf和double的问题

我无法理解为什么会发生这种情况:使用以下代码;

#include  int main() { double x=123; printf("x is %f. Enter a new value for x.\n", x); scanf("%f", &x); printf("x is %f\n", x); return 0; } 

当您输入45678作为x的新值时,将打印“x为123.000017”。 我知道在扫描时使用%lf时这是固定的,但为什么在使用%f时会发生这种情况?

我知道在扫描时使用%lf时这是固定的,但为什么在使用%f时会发生这种情况?

printfscanf函数参数之间的区别在于您将值传递给printf ,但是对于scanf您传递指针(即值的地址)。 根据C规则,当函数采用可变数量的参数时,所有参数都会进行默认促销

其中一个促销是float被转换为double ,就像short s转换为int 。 这就是为什么你可以使用%f%lfprintf :编译器将两种类型的值转换为double ,因此访问它们是安全的。

但是,指针没有这样的规则(并且有充分的理由:尝试将double写入float的空间将是未定义的行为)。 这就是为什么在将参数传递给scanf系列函数时必须区分%f%lf的原因。

  scanf("%f", &x); 

应该

  scanf("%lf", &x); 

printfscanf之间的浮点转换说明符存在错误对称性。

另请注意, lf转换说明符等同于printf f转换说明符(因为c99,之前未定义)。

我知道在扫描时使用%lf时这是固定的,但为什么在使用%f时会发生这种情况?

scanf f转换说明符需要一个float类型指针的参数。 通过将类型指针的参数传递给double可以调用未定义的行为。