2008-10-16 3 views
162

Почему scanf() нуждается l в «%lf» при чтении double, когда printf() может использовать «%f» независимо от того, является ли ее аргумент является double или float?Почему scanf() нуждается в «% lf» для удвоений, когда printf() в порядке с «% f»?

Пример кода:

double d; 
scanf("%lf", &d); 
printf("%f", d); 
+1

Я не понимаю, что вы подразумеваете под POINTER здесь. В scanf мы передаем только адрес переменной (т.е.), где находится указатель – 2012-06-17 13:04:38

+7

@deetchanya В C, когда вы «берете адрес» переменной с унарным оператором `&`, результатом этой операции является указатель на место хранения переменной в памяти. Это указатель, который передается `scanf`. – zwol 2013-06-27 23:03:03

+0

это еще одно сообщение об этом https: // stackoverflow.com/questions/9291348/why-is-scanf-not-working-as-expected-when-writing-to-a-string-literal – vimalpt 2014-09-22 10:03:52

ответ

192

Поскольку C будет способствовать поплавки двойников для функций, которые принимают переменные аргументы. Указатели не продвигаются ни на что, поэтому вы должны использовать %lf, %lg или %le (или %la в C99) для чтения в двухместных номерах.

+3

По умолчанию аргументы по умолчанию являются стандартными C, а не только MSVC. – 2008-10-16 23:14:24

+0

Исправлено в соответствии с вашими комментариями. УРА! – MSN 2008-10-16 23:25:09

16

scanf должен знать размер данных, на который указывает &d, чтобы заполнить его должным образом, в то время как VARIADIC функции способствуют поплавки в парном разряде (не совсем уверен, почему), так printf всегда получает double.

2

Использование значения float или double в выражении C приведет к тому, что значение равно double, поэтому printf не может отличить эту разницу. В то время как указатель на double должен быть явно передан scanf в отличие от указателя на float, поскольку то, что указывает указатель, имеет значение.

7

Потому что иначе scanf будет думать, что вы передаете указатель на float, размер которого меньше, чем двойной, и он вернет неправильное значение.

20

С С99 соответствие между спецификаторами формата и типами аргументов с плавающей запятой в C согласовано между printf и scanf. Это

  • %f для float
  • %lf для double
  • %Lf для long double

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

Но нет оснований на практике делать это на практике. Не используйте %f аргументам printf типа double. Это широко распространенная привычка, появившаяся в C89/90 раз, но это плохая привычка. Используйте %lf в printf для double и сохраните %f для float аргументов.