Глиф Учебники

Чем %f отличается от %lf в scanf и printf

Справочник · C · 1 минута чтения

Коротко:

Типscanfprintf
float%f%f
double%lf%f или %lf
long double%Lf%Lf

То есть в scanf буква l обязательна для double, а в printf для double годятся оба варианта.

C
#include <stdio.h>

int main(void) {
    float f;
    double d;
    scanf("%f %lf", &f, &d);
    printf("%f %f\n", f, d);
    printf("%.2lf\n", d);
    return 0;
}
Ввод
1.5 2.25
Вывод
1.500000 2.250000
2.25

Почему в scanf есть разница

scanf получает адрес переменной и должен записать туда число в нужном виде. float занимает 4 байта, double — 8, устроены они по-разному. Формат говорит scanf, что именно лежит по адресу. Если прочитать double через %f, в переменную запишутся 4 байта в виде float — получится бессмысленное значение, часто очень маленькое или ноль. gcc с -Wall предупреждает:

Текст
warning: format '%f' expects argument of type 'float *', but argument 2 has type 'double *' [-Wformat=]

Почему в printf разницы нет

Дробное значение, переданное в printf, по правилам языка всегда превращается в double — даже если переменная была float. Поэтому printf получает только double, и %f для него — правильный формат. Запись %lf в printf стандарт C99 тоже разрешил и сделал равной %f. В очень старых компиляторах, до C99, %lf в printf могла не работать — отсюда советы «в printf только %f».

Другие форматы дробных чисел

C
#include <stdio.h>

int main(void) {
    double x = 1234.5;
    printf("%f | %.1f | %e | %g\n", x, x, x, x);
    printf("%g\n", 0.0000001);
    return 0;
}
Вывод
1234.500000 | 1234.5 | 1.234500e+03 | 1234.5
1e-07

Частые ошибки