Почему scanf() нуждается в "% lf" для удвоений, когда printf() в порядке с "% f"?
Почему scanf()
нуждается в l
в "%lf
" при чтении double
, когда printf()
может использовать "%f
" независимо от того, является ли его аргумент double
или float
?
Пример кода:
double d;
scanf("%lf", &d);
printf("%f", d);
Ответы
Ответ 1
Потому что C будет поддерживать float в double для функций, которые принимают переменные аргументы. Указатели не продвигаются ни на что, поэтому вы должны использовать %lf
, %lg
или %le
(или %la
в C99) для чтения в двухлокальных номерах.
Ответ 2
С С99 соответствие между спецификаторами формата и типами аргументов с плавающей запятой в C согласовано между printf
и scanf
.
-
%f
для float
-
%lf
для double
-
%lf
для long double
Так получилось, что когда аргументы типа float
передаются как переменные параметры, такие аргументы неявно преобразуются в тип double
. Именно поэтому спецификаторы формата printf
%f
и %lf
эквивалентны и взаимозаменяемы. В printf
вы можете "перекрестно использовать" %lf
с помощью float
или %f
с помощью double
.
Но нет оснований на самом деле делать это на практике. Не используйте аргументы %f
to printf
типа double
. Это широко распространенная привычка, появившаяся в C89/90 раз, но это плохая привычка. Используйте %lf
в printf
для double
и сохраните %f
для аргументов float
.
Ответ 3
scanf
должен знать размер данных, на которые указывает &d
, чтобы заполнить его должным образом, тогда как вариативные функции поддерживают float в double (не совсем уверен, почему), поэтому printf
всегда получает double
.
Ответ 4
Потому что иначе scanf подумает, что вы передаете указатель на float, размер которого меньше, чем двойной, и он вернет неправильное значение.
Ответ 5
Использование значения float или double в выражении C приведет к тому, что значение равно double, поэтому printf не может отличить эту разницу. В то время как указатель на double должен быть явно передан scanf в отличие от указателя на float, поскольку то, что указывает указатель, имеет значение.