Antworten:
Das liegt daran, %ddass erwartet wird, intaber Sie haben einen Float bereitgestellt.
Verwenden Sie %e/ %f/ %gden Schwimmer zu drucken.
Warum 0 gedruckt wird: Die Gleitkommazahl wird doublevor 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 %dverbraucht 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 floatkonvertiert ?doubleint 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
floatwerden heraufgestuftdouble. Diese werden als Standardargumentwerbung bezeichnet .
(Danke Alok, dass du das herausgefunden hast.)
printfes sich um eine variadische Funktion handelt und der Standard besagt, dass für variadische Funktionen a vor dem Übergeben in a floatkonvertiert wird double.
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 , printfindem Sie ‚Verhalten , was Sie tun , ist nicht von großem Nutzen sein wird. Möglicherweise versuchen Sie, das Verhalten printfIhres Systems zu untersuchen. In diesem Fall sollten Sie die Dokumentation lesen und im Quellcode nachsehen, printfob er für Ihre Bibliothek verfügbar ist.
Auf meinem Macbook erhalte ich beispielsweise die Ausgabe 1606416304mit Ihrem Programm.
Wenn Sie jedoch a floatan eine variable Funktion übergeben, floatwird das als übergeben double. Ihr Programm entspricht also der Deklaration aals double.
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:
#include <stdio.h>
int main(void)
{
double a = 1234.5f;
unsigned char *p = (unsigned char *)&a;
size_t i;
printf("size of double: %zu, int: %zu\n", sizeof(double), sizeof(int));
for (i=0; i < sizeof a; ++i)
printf("%02x ", p[i]);
putchar('\n');
return 0;
}
Wenn ich das obige Programm ausführe, erhalte ich:
size of double: 8, int: 4
00 00 00 00 00 4a 93 40
Die ersten vier Bytes von haben doublesich also als 0 herausgestellt, weshalb Sie möglicherweise 0die Ausgabe Ihres printfAnrufs erhalten haben.
Für interessantere Ergebnisse können wir das Programm ein wenig ändern:
#include <stdio.h>
int main(void)
{
double a = 1234.5f;
int b = 42;
printf("%d %d\n", a, b);
return 0;
}
Wenn ich das obige Programm auf meinem Macbook ausführe, erhalte ich:
42 1606416384
Mit dem gleichen Programm auf einem Linux-Computer bekomme ich:
0 1083394560
intArgumente in anderen Registern als doubleArgumente übergeben werden. printfmit %dnimmt das intArgument, das 42 ist, und das zweite %ddruckt wahrscheinlich Junk, da es kein zweites intArgument gab.
Der %dBezeichner gibt printfan, 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 gedruckt
Die binäre Darstellung von 1234.5 ist so etwas wie
1.00110100101 * 2^10 (exponent is decimal ...)
Bei einem C-Compiler, der floattatsächlich als IEEE754-Doppelwerte dargestellt wird, wären die Bytes (wenn ich keinen Fehler gemacht hätte)
01000000 10010011 01001010 00000000 00000000 00000000 00000000 00000000
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 printfgedruckt ...
In diesem Wikipedia-Artikel finden Sie eine Gleitkomma-Darstellung gemäß IEEE754.
Es liegt an der Darstellung eines Floats in Binärform. Bei der Konvertierung in eine Ganzzahl bleibt 0 übrig.
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.
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 ist int(und das ist es, womit Sie sagen %d), glaubt es Ihnen und es braucht nur die Bytes, die für ein benötigt werden int. In diesem Fall, wenn Ihr Computer vier Byte intund acht Byte verwendet double(das floatwird in ein doubleInneres konvertiert printf()), sind die ersten vier Bytes anur Nullen, und dies wird gedruckt.
Da Sie es auch mit C ++ markiert haben, führt dieser Code die Konvertierung wie erwartet durch:
#include <iostream.h>
int main() {
float a = 1234.5f;
std::cout << a << " " << (int)a << "\n";
return 0;
}
Ausgabe:
1234.5 1234
%d ist dezimal
%f ist float
Weitere davon finden Sie hier .
Sie erhalten 0, weil Gleitkommazahlen und Ganzzahlen unterschiedlich dargestellt werden.
Sie müssen nur den entsprechenden Formatbezeichner (% d,% f,% s usw.) Mit dem entsprechenden Datentyp (int, float, string usw.) verwenden.
Es ist keine ganze Zahl. Versuchen Sie es mit %f.