Подтвердить что ты не робот

Scanf/Printf двойная переменная C

Скажем, у меня есть следующий бит кода в C:

double var;
scanf("%lf", &var);
printf("%lf", var);
printf("%f", var);

Он читает из переменной stdin 'var', а затем дважды печатает в stdout 'var'. Я понимаю, что вы читаете двойную переменную из stdin, но мои вопросы:

  • Почему вы можете печатать двойной с помощью% lf?
  • Почему вы можете печатать двойной с% f?
  • Какая из них лучше и правильнее использовать?
4b9b3361

Ответ 1

Для переменных аргументов, таких как printf и scanf, аргументы продвигаются, например, любые более мелкие целые типы повышаются до int, float продвигается до double.

scanf принимает параметры указателей, поэтому правило продвижения не действует. Он должен использовать %f для float* и %lf для double*.

printf никогда не увидит аргумент float, float всегда продвигается до double. Спецификатор формата %f. Но C99 также говорит, что %lf совпадает с %f в printf:

C99 §7.19.6.1 Функция fprintf

l (ell) Указывает, что для аргумента long int или unsigned long int применяется следующий d, i, o, u, x или x; что следующий указатель преобразования n применяется к указателю на аргумент long int; что для аргумента wint_t применяется следующий спецификатор преобразования c; что следующий указатель преобразования s применяется к указателю на аргумент wchar_t; или не влияет на следующие a, a, e, e, f, f, g или g спецификатор преобразования.

Ответ 2

Насколько я читаю страницы руководства, scanf говорит, что модификатор длины l указывает (в случае плавающих точек), что аргумент имеет тип double, а не тип float, поэтому вы можете иметь lf, le, lg.

Что касается печати, официально в руководстве говорится, что "l" применяется только к целым типам. Поэтому он может не поддерживаться некоторыми системами или некоторыми стандартами. Например, при компиляции с gcc -Wall -Wextra -pedantic

появляется следующее сообщение об ошибке:
a.c:6:1: warning: ISO C90 does not support the ‘%lf’ gnu_printf format [-Wformat=]

Таким образом, вам может потребоваться удвоить, если ваш стандарт поддерживает синтаксис.

В заключение я бы сказал, что вы читаете "% lf", и вы печатаете с "% f".

Ответ 3

Когда a float передается в printf, он автоматически преобразуется в double. Это часть рекламных акций по умолчанию, которые применяются к функциям, которые имеют список переменных параметров (содержащий ...), в основном по историческим причинам. Поэтому "естественный" спецификатор для float, %f должен работать с аргументом double. Поэтому спецификаторы %f и %lf для printf одинаковы; они оба принимают значение double.

Когда вызывается scanf, указатели передаются, а не прямые значения. Указатель на float не преобразуется в указатель на double (это не сработало, поскольку объект с указателем не может измениться при изменении типа указателя). Итак, для scanf аргумент для %f должен быть указателем на float, а аргумент для %lf должен быть указателем на double.