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