Чому scanf () потрібен "% lf" для парних, коли printf () нормально лише "% f"?


179

Чому саме він scanf()потребує l" %lf" під час читання a double, коли printf()може використовувати " %f", незалежно від того, його аргумент є a doubleчи a float?

Приклад коду:

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

1
Я не розумію, що ви тут маєте на увазі під POINTER. У scanf ми лише передаємо & змінну (тобто) адресу, тож де вказівник

7
@deetchanya У C, коли ви "приймаєте адресу" змінної разом з одинарним &оператором, результатом цієї операції є вказівник на місце зберігання змінної в пам'яті. Саме той вказівник передається scanf.
zwol

це ще один пост про це stackoverflow.com/questions/9291348 / ...
vimalpt

Відповіді:


207

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


26

Оскільки С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аргументів.


1
Я б сказав, що використання %fв printf - це хороша звичка, оскільки тоді ваш код завжди працює, тоді як використання %lfможе не вдатися, якщо у компілятора немає бібліотеки, сумісної з C99. На жаль, така ситуація насправді відбувається.
ММ

Оскільки С99, відповідність між специфікаторами формату та типом аргументів з плаваючою комою в C відповідає між printfта scanf. Зауважте, що це не означає, що використання одного і того ж специфікатора формату означає, що дані, записані а, [f]printf()можуть бути прочитані [f]scanf(). Загалом, використовуючи той же формат специфікатор для scanf()який був використаний printf()буде НЕ успішно лічені дані. Так , наприклад, простір оббивка , яка може бути вставлена з допомогою prinf()«S "%d"специфікатор формату буде пропущена до того ж "%d"специфікатор формату в scanf()виклику.
Ендрю Генле

16

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


1
Варіатична функція є дуже крихкою, тому що вона повинна бути в змозі знати точний тип і розмір усіх параметрів, переданих їй, і вона не може застосувати це під час компіляції. Якщо змінна неправильного типу, буде прочитане неправильне значення; якщо це неправильний розмір, всі змінні після будуть також неправильно прочитані. Якби два різних розміри поплавця могли бути передані, це спричинило б усілякі неприємні та легко пропускаючі проблеми.
mwfearnley

7

Тому що в іншому випадку scanf подумає, що ви передаєте вказівник на поплавок, який має менший розмір, ніж у подвійний, і він поверне неправильне значення.


2

Використання або float, або подвійне значення у виразі C призведе до значення, яке все одно є подвійним, тому printf не може визначити різницю. Тоді як вказівник на подвійний повинен бути чітко сигналізований, щоб сканувати як відмітний від вказівника для плавання, адже те, що вказує на вказівник, є важливим.


5
float перетворюється в подвійний у цьому випадку, оскільки аргументи є частиною аргументу списку аргументів змінної довжини, floats не завжди перетворюються на подвійні в C.
Роберт Гембл

1
У попередніх стандартних версіях floatзначення мови автоматично висуваються doubleу виразах. Це правило було відмовлено в стандарті C. Взагалі, floatйого не пропонують doubleу виразах. До doubleнього звертаються лише тоді, коли його передають як різноманітний аргумент, що і відбувається в цьому випадку.
ANT
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.