Das liegt daran, %d
dass erwartet wird, int
aber Sie haben einen Float bereitgestellt.
Verwenden Sie %e
/ %f
/ %g
den Schwimmer zu drucken.
Warum 0 gedruckt wird: Die Gleitkommazahl wird double
vor dem Senden an konvertiert printf
. Die Zahl 1234.5 in doppelter Darstellung in Little Endian ist
00 00 00 00 00 4A 93 40
A %d
verbraucht eine 32-Bit-Ganzzahl, sodass eine Null gedruckt wird. (Als Test könnten printf("%d, %d\n", 1234.5f);
Sie Sie könnten auf Ausgabe bekommen 0, 1083394560
.)
Warum wird der als Prototyp von printf von 6.5.2.2/7 float
konvertiert ?double
int printf(const char*, ...)
Die Auslassungsnotation in einem Funktionsprototyp-Deklarator bewirkt, dass die Konvertierung des Argumenttyps nach dem zuletzt deklarierten Parameter gestoppt wird. Die Standardargumentwerbung wird für nachfolgende Argumente durchgeführt.
und vom 6.5.2.2/6,
Wenn der Ausdruck, der die aufgerufene Funktion bezeichnet, einen Typ hat, der keinen Prototyp enthält, werden die Ganzzahl-Heraufstufungen für jedes Argument ausgeführt und Argumente mit Typ float
werden heraufgestuft double
. Diese werden als Standardargumentwerbung bezeichnet .
(Danke Alok, dass du das herausgefunden hast.)
printf
es sich um eine variadische Funktion handelt und der Standard besagt, dass für variadische Funktionen a vor dem Übergeben in afloat
konvertiert wirddouble
.printf()
ruft Undefiniertes Verhalten auf .Technisch gibt sprechen , ist nicht die
printf
, die jeweils ihre Bibliothek implementiert eigene, und daher Ihre Methode der zu Studie versucht ,printf
indem Sie ‚Verhalten , was Sie tun , ist nicht von großem Nutzen sein wird. Möglicherweise versuchen Sie, das Verhaltenprintf
Ihres Systems zu untersuchen. In diesem Fall sollten Sie die Dokumentation lesen und im Quellcode nachsehen,printf
ob er für Ihre Bibliothek verfügbar ist.Auf meinem Macbook erhalte ich beispielsweise die Ausgabe
1606416304
mit Ihrem Programm.Wenn Sie jedoch a
float
an eine variable Funktion übergeben,float
wird das als übergebendouble
. Ihr Programm entspricht also der Deklarationa
alsdouble
.Um die Bytes von a zu untersuchen
double
, können Sie diese Antwort auf eine aktuelle Frage hier auf SO sehen.Lass uns das tun:
Wenn ich das obige Programm ausführe, erhalte ich:
Die ersten vier Bytes von haben
double
sich also als 0 herausgestellt, weshalb Sie möglicherweise0
die Ausgabe Ihresprintf
Anrufs erhalten haben.Für interessantere Ergebnisse können wir das Programm ein wenig ändern:
Wenn ich das obige Programm auf meinem Macbook ausführe, erhalte ich:
Mit dem gleichen Programm auf einem Linux-Computer bekomme ich:
quelle
int
Argumente in anderen Registern alsdouble
Argumente übergeben werden.printf
mit%d
nimmt dasint
Argument, das 42 ist, und das zweite%d
druckt wahrscheinlich Junk, da es kein zweitesint
Argument gab.Der
%d
Bezeichner gibtprintf
an, eine Ganzzahl zu erwarten. Die ersten vier (oder zwei, je nach Plattform) Bytes des Floats werden also als Ganzzahl interpretiert. Wenn sie zufällig Null sind, wird eine Null gedrucktDie binäre Darstellung von 1234.5 ist so etwas wie
Bei einem C-Compiler, der
float
tatsächlich als IEEE754-Doppelwerte dargestellt wird, wären die Bytes (wenn ich keinen Fehler gemacht hätte)Auf einem Intel (x86) -System mit geringer Endianess (dh das niedrigstwertige Byte steht an erster Stelle) wird diese Bytesequenz umgekehrt, sodass die ersten vier Bytes Null sind. Das heißt, was wird
printf
gedruckt ...In diesem Wikipedia-Artikel finden Sie eine Gleitkomma-Darstellung gemäß IEEE754.
quelle
Es liegt an der Darstellung eines Floats in Binärform. Bei der Konvertierung in eine Ganzzahl bleibt 0 übrig.
quelle
Weil Sie undefiniertes Verhalten aufgerufen haben: Sie haben den Vertrag der printf () -Methode verletzt, indem Sie sie über ihre Parametertypen belogen haben, sodass der Compiler frei tun kann, was er will. Es könnte dazu führen, dass das Programm "dksjalk is a ninnyhead !!!" und technisch wäre es immer noch richtig.
quelle
Der Grund ist, dass dies
printf()
eine ziemlich dumme Funktion ist. Typen werden überhaupt nicht überprüft. Wenn Sie sagen, dass das erste Argument ein istint
(und das ist es, womit Sie sagen%d
), glaubt es Ihnen und es braucht nur die Bytes, die für ein benötigt werdenint
. In diesem Fall, wenn Ihr Computer vier Byteint
und acht Byte verwendetdouble
(dasfloat
wird in eindouble
Inneres konvertiertprintf()
), sind die ersten vier Bytesa
nur Nullen, und dies wird gedruckt.quelle
Float wird nicht automatisch in eine Ganzzahl konvertiert. Weil beide unterschiedliche Speicherformate haben. Wenn Sie also konvertieren möchten, verwenden Sie (int) typecasting.
quelle
Da Sie es auch mit C ++ markiert haben, führt dieser Code die Konvertierung wie erwartet durch:
Ausgabe:
quelle
%d
ist dezimal%f
ist floatWeitere davon finden Sie hier .
Sie erhalten 0, weil Gleitkommazahlen und Ganzzahlen unterschiedlich dargestellt werden.
quelle
Sie müssen nur den entsprechenden Formatbezeichner (% d,% f,% s usw.) Mit dem entsprechenden Datentyp (int, float, string usw.) verwenden.
quelle
Sie wollen% f nicht% d
quelle
Hey, es musste etwas drucken, damit es eine 0 druckte. Denken Sie daran, in C 0 ist alles andere!
quelle
Es ist keine ganze Zahl. Versuchen Sie es mit
%f
.quelle