Когда вы хотите напечатать значение типа float
или double
с помощью функции printf()
, вы используете спецификатор %f
для обоих типов данных. Например:
double d = 3.5;
float f = 4.5;
printf("Valores: %f %f", f, d);
В то время как в случае функции scanf()
спецификатор используется %f
для чтения a float
и спецификатор %lf
для чтения a double
:
double d;
float f;
printf("Introduce un float y un double: ");
scanf("%f %lf", &f, &d);
Почему существуют разные спецификаторы для типов float
и double
в scanf()
, но один и тот же спецификатор в printf()
?
Язык C выполняет неявное преобразование из
float
в,double
когда значение типа передается в качестве аргументаfloat
функции с переменным числом аргументов , как в случае функцииprintf()
. Таким образом, независимо от того, передается ли значениеfloat
или передается adouble
, функцияprintf()
получает значениеdouble
, при этом спецификатор настроен%f
на печать значений типаdouble
вprintf()
В случае
scanf()
значений (типfloat
илиdouble
) не передаются в качестве аргументов, а передаются указатели с адресами памяти, где хранить прочитанные значения. Указатели не конвертируются C неявно, помимо того, что функцияscanf()
должна знать, какого типа данные имеет каждая из переменных, где она собирается хранить каждое прочитанное значение, чтобы не занимать области памяти больше зарезервированных или нет. сохранить данные в неправильном формате в соответствующую переменную. Поэтому для каждой переменной необходим конкретный спецификатор с соответствующим типом данных.Начиная со стандарта C99 , для каждого типа данных с плавающей запятой устанавливается специальный спецификатор, как для , так
printf()
и дляscanf()
:При использовании функции
printf()
со спецификатором%f
можно безопасно использовать аргументы типаfloat
илиdouble
. Кроме того, нет никакой разницы использовать%f
или%lf
со значениями типаfloat
илиdouble
. Во всех возможных комбинациях между нимиprintf()
он неявно преобразуетdouble
и печатает его как таковой. Но использование спецификатора%lf
со значениямиfloat
или%f
со значениямиdouble
считается плохой практикой и его следует избегать, даже если изначально это не вызывает проблем.Для написания этого решения использовалась большая часть информации из записи SO на английском языке: https://stackoverflow.com/questions/210590/why-does-scanf-need-lf-for-doubles-when-printf -is- хорошо-с-просто-f