2010-02-16 19 views
9

Ich arbeitete an diesem Programm und mir fiel auf, dass die Verwendung von% f für ein Double und% d für einen Float etwas völlig anderes ergibt. Weiß jemand, warum das passiert?C printf mit% d und% f

int main() 
{ 
float a = 1F; 
double b = 1; 

printf("float =%d\ndouble= %f", a, b); 
} 

Dies ist die Ausgabe

float = -1610612736 
double = 190359837192766135921612671364749893774625551025007120912096639276776057269784974988808792093423962875123204096.0000 
+0

bedankt sich bei allen für die Kommentare. Ich verstehe es jetzt. – user69514

Antwort

4

Aufgrund der Funktionsweise der variablen Parameter hat C keine Vorstellung davon, welchen Wert Sie gerade übergeben, außer %d und %f. Wenn Sie einen variablen Parameter übergeben, tun Sie im Grunde (void*)&myvalue, weil weder der Compiler noch die Funktion zur Laufzeit den Typ der Variablen bestimmen können, außer was in der Formatierungszeichenfolge angegeben ist. Obwohl eine implizite Konvertierung verfügbar ist, weiß der Compiler nicht, dass er benötigt wird.

Nun, Double ist 8 Bytes auf den meisten Systemen, während Float 4 Bytes ist. Die beiden Typen sind also nicht binärkompatibel. Und es ist so, als würde man versuchen, eine Zeichenkette als einen doppelten oder einen anderen inkompatiblen Typ zu interpretieren.

+2

Korrekt, aber es geht nicht wirklich um die Kompatibilität zwischen 'float' und' double'. Tatsächlich werden variadische Argumente vom Typ "float" vor dem Übergehen immer zu "double" befördert, was bedeutet, dass der Typ "float" an nichts beteiligt ist. Beide Werte, die an printf übergeben werden, haben den Typ "double". Im Inneren wird der erste als "int" interpretiert (wegen '% d' Spezifizierer). Die Inkompatibilität zwischen "int" und "double" verursacht das beobachtete undefinierte Verhalten. – AnT

3

Es mit internen Darstellungen von Daten zu tun hat. Sie versuchen, ein Float zu drucken, als wäre es ein int, das eine völlig andere interne (binäre) Darstellung hat.

Die Doppel Fall ist ähnlich. Wahrscheinlich haben Sie nach der float-Variablen einen Müll (beliebige Daten). Dieser Müll wird als Teil des doppelten Werts interpretiert.

4

%d steht für dezimal und erwartet ein Argument vom Typ int (oder ein kleinerer Typ mit Vorzeichen mit Vorzeichen, der dann hochgestuft wird). Die Gleitkommatypen float und double werden beide auf die gleiche Weise übergeben (zu double befördert) und beide verwenden %f. In C99 können Sie auch %lf verwenden, um die größere Größe von double zu kennzeichnen, aber das ist rein kosmetisch (beachten Sie, dass mit scanf keine Förderung auftritt und dies tatsächlich einen Unterschied macht).

+0

Nun, das ist wahr http://codepad.org/labE8lgy, aber ich frage mich, wie das eigentlich funktioniert .. – Earlz

0

% d druckt eine ganze Zahl, so dass Ihr printf Ihre Variable a als int interpretiert.

Mit gcc 3.4.6, bekomme ich 0 für beide Werte mit Ihrem Code (nachdem das F aus der a-Initialisierung genommen wurde, da dies zu einem Compilerfehler führte). Ich vermute, das hat mit dem Teil der a-Variablen zu tun, der als int interpretiert wird, was 0 ist, und dann wird der Compiler verwirrt ... (es gibt wahrscheinlich eine bessere Erklärung, aber ich kann nicht darüber nachdenken).

Verwenden von% f für beide Variablen Drucke 1,000000 für beide Variablen für mich.

Sie können eine Liste der Konvertierungszeichen am unteren Rand dieser Seite finden:

http://www.exforsys.com/tutorials/c-language/managing-input-and-output-operations-in-c.html

+0

Der Compiler-Fehler, der mit "F" verknüpft ist, liegt darin, dass er nicht an eine ganze Zahl angehängt werden kann (z. B. ist "1.0F" in Ordnung). – RastaJedi