Warum benötigt scanf () "% lf" für Doppel, wenn printf () nur mit "% f" einverstanden ist?

179

Warum scanf()braucht es das lin " %lf" beim Lesen von a double, wann printf()kann " %f" verwendet werden, unabhängig davon, ob sein Argument a doubleoder a ist float?

Beispielcode:

double d;
scanf("%lf", &d);
printf("%f", d);
Raldi
quelle
1
Ich verstehe nicht, was du hier mit POINTER meinst. In scanf übergeben wir nur & variable (dh) Adresse, also wo ist der Zeiger
7
@deetchanya Wenn Sie in C mit dem unären &Operator die Adresse einer Variablen "nehmen" , ist das Ergebnis dieser Operation ein Zeiger auf den Speicherort der Variablen im Speicher. Es ist dieser Zeiger, an den übergeben wird scanf.
zwol
Dies ist ein weiterer Beitrag zu diesem stackoverflow.com/questions/9291348/…
vimalpt

Antworten:

207

Weil C Floats für Funktionen, die variable Argumente annehmen, auf Double hochfährt. Zeiger sind nicht auf etwas gefördert, so sollten Sie verwenden %lf, %lgoder %le(oder %lain C99) im Doppel zu lesen.

MSN
quelle
26

Seit С99 ist die Übereinstimmung zwischen Formatbezeichnern und Gleitkomma-Argumenttypen in C zwischen printfund konsistent scanf. Es ist

  • %f zum float
  • %lf zum double
  • %Lf zum long double

Es kommt einfach so vor, dass floatsolche Argumente implizit in Typ konvertiert werden , wenn Argumente vom Typ als variable Parameter übergeben werden double. Dies ist der Grund, warum in printfFormatbezeichnern %fund %lfgleichwertig und austauschbar sind. In können printfSie %lfmit floatoder %fmit "Cross-Use" double.

Aber es gibt keinen Grund, dies tatsächlich in der Praxis zu tun. Verwenden Sie nicht %fauf printfArgumente des Typs double. Es ist eine weit verbreitete Angewohnheit, die in C89 / 90-mal geboren wurde, aber es ist eine schlechte Angewohnheit. Verwenden Sie %lfin printffür doubleund behalten Sie %fsich floatArgumente vor.

Ameise
quelle
1
Ich würde sagen, dass die Verwendung %fin printf eine gute Angewohnheit ist, da dann Ihr Code immer funktioniert, während die Verwendung %lfmöglicherweise fehlschlägt, wenn der Compiler keine C99-kompatible Bibliothek hat. Leider passiert diese Situation in der Realität.
MM
Seit С99 ist die Übereinstimmung zwischen Formatbezeichnern und Gleitkomma-Argumenttypen in C zwischen printfund konsistent scanf. Beachten Sie, dass dies nicht bedeutet, dass die Verwendung desselben Formatbezeichners bedeutet, dass die von a geschriebenen Daten von [f]printf()gelesen werden können [f]scanf(). Im Allgemeinen werden die Daten nicht erfolgreich gelesen scanf(), wenn derselbe Formatbezeichner verwendet printf()wird , der von verwendet wurde. Zum Beispiel , die Raumpolsterung durch einen eingeschoben werden kann ‚s - Format - Spezifizierer werden von denselben übersprungen werden Formatbezeich in einem Anruf. prinf()"%d""%d"scanf()
Andrew Henle
16

scanfmuss die Größe der Daten kennen, auf die verwiesen wird &d, um sie richtig zu füllen, wohingegen verschiedene Funktionen Floats auf Doppelwerte bringen (nicht ganz sicher warum), so dass printfimmer ein erhalten wird double.

Tanktalus
quelle
1
Eine variable Funktion ist sehr fragil, da sie den genauen Typ und die Größe aller an sie übergebenen Parameter kennen muss und dies beim Kompilieren nicht erzwingen kann. Wenn eine Variable vom falschen Typ ist, wird der falsche Wert gelesen. Wenn es die falsche Größe hat, werden auch alle Variablen danach falsch gelesen. Wenn zwei verschiedene Schwimmergrößen passiert werden könnten, würde dies alle Arten von bösen und leicht zu übersehenden Problemen verursachen.
mwfearnley
7

Andernfalls wird scanf glauben, dass Sie einen Zeiger auf einen Float übergeben, der kleiner als ein Double ist, und einen falschen Wert zurückgeben.

Jim Buck
quelle
2

Die Verwendung eines Gleitkomma- oder Doppelwerts in einem C-Ausdruck führt ohnehin zu einem Doppelwert, sodass printf den Unterschied nicht erkennen kann. Während ein Zeiger auf ein Double explizit an scanf signalisiert werden muss, im Gegensatz zu einem Zeiger auf float, ist es wichtig, worauf der Zeiger zeigt.

fcw
quelle
5
float wird in diesem Fall in ein Double konvertiert, da die Argumente Teil einer Argumentliste mit variabler Länge sind. Floats werden in C nicht immer in Doubles konvertiert.
Robert Gamble
1
In Vor-Standard-Versionen von C wurden Sprachwerte floatautomatisch doublein Ausdrücken heraufgestuft. Diese Regel wurde in Standard C aufgegeben. Wird im Allgemeinen floatnicht doublein Ausdrücken befördert. Es wird nur befördert, doublewenn es als variadisches Argument übergeben wird, was in diesem Fall der Fall ist.
Am