Почему 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, поскольку то, что указывает указатель, имеет значение.