double Variable mit %d ausgeben



  • Hallo Leute!

    Ich befinde mich grade mitten in der Prüfungsvorbereitung im Fach Programmieren 1. Nun häng ich grade irgendwie bei folgender Aufgabe:

    Ich soll herausfinden, was das Programm ausgibt. Ich bin schon so weit, dass ich weiß, dass b: und c: ausgegeben wird. Allerdings ist bei den printf's ja %d angegeben, wo eigentlich %f stehen sollte.
    Das erzeugt dann beim auführen des Programms eine recht komische Ausgabe:
    b: 0
    c: 343597384

    Müsste dort nicht eigentlich einfach von double auf int gecastet werden und somit die Werte b: 1 und c: 1 lauten?

    Als IDE benutze ich Dev C++ (MinGW).

    #include <stdio.h>
    
    int main (int argc, char *argv[])
    {
    
    	double a = 50.0;
    	double b = 1.5;
    	double c = 1.33;
    
    	if (a == 50.0)
    		if (b < 10.0 * 10.0 && c < 1.33)
    			printf("a: %d\n",a);
    		else
    			printf("b: %d\n",b);
    	if (c > 0)
    		printf("c: %d\n",c);
    
    	return 0;
    }
    

  • Mod

    Wenn du beim Funktionsaufruf castest ( printf("%d", (int)b); ), wird das von dir erwartete Ergebnis herauskommen. Aber wenn es so gemacht wird wie hier, dann bekommt man Probleme, weil printf nicht typsicher ist. Der double wird so wie er ist an die Funktion übergeben. Diese interpretiert (zur Laufzeit!) den Formatstring und sieht, dass sie das nächste Argument so ausgeben soll, als wäre es ein Integer. Es wird also auch da drauf zugegriffen, als wären die Daten ein Integer. Es ist aber ein double und die Bitrepräsentation von Zahlen in einem double ist eine ganz andere als in Integern, wenn man diese Muster wie einen Integer interpretiert kommt daher irgendein wilder Wert raus. Das ganze ist zudem hochgradig undefiniertes Verhalten, allein schon das double und int auf den meisten Systemen unterschiedliche Größen haben wird für Probleme sorgen.



  • Vielen Dank für die ausführliche Antwort!
    Ich vermute mal der Professor wollte, dass wir da drüber stolpern 🙂

    Wieder etwas schlauer 👍


  • Mod

    marcm244 schrieb:

    Ich vermute mal der Professor wollte, dass wir da drüber stolpern 🙂

    Erstaunlich viele Leute denken: %i = int, %f = float und dann logischerweise %d = double 🙂



  • Wär aber auch sinnvoller 😃



  • marcm244 schrieb:

    Wär aber auch sinnvoller 😃

    Nö.
    Da printf eine Funktion mit variabler Argumentenliste ist, bekommt es auch bei float double-Werte zu sehen.

    Das %d steht für dezimal.

    Das %i ist bei printf nicht unbedingt nötig.



  • Da printf eine Funktion mit variabler Argumentenliste ist, bekommt es auch bei float double-Werte zu sehen.

    Kapier ich ned ganz 😕

    Sry, bin noch nicht so bewandert in C 😞


  • Mod

    marcm244 schrieb:

    Da printf eine Funktion mit variabler Argumentenliste ist, bekommt es auch bei float double-Werte zu sehen.

    Kapier ich ned ganz 😕

    Regeln für Funktionen mit variablen Argumentenlisten. Demnach werden alle Argumente erst einmal der "default argument promotion" ausgesetzt, bevor sie an die Funktion übergeben werden:

    C Standard schrieb:

    If the expression that denotes the called function has a type that does not include a
    prototype, the integer promotions are performed on each argument, and arguments that
    have type float are promoted to double. These are called the default argument
    promotions.



  • Und darum ist der Formatspecifier %lf für printf auch erst mit C11 in den Standard aufgenommen worden.
    Aus Resignation.



  • @ SeppJ
    Danke! Hab mich gleich mal drüber informiert!

    @DirkB
    Gut zu wissen, ich hab nämlich bis jetzt des öfteren mal %lf geschrieben und das darf ich nicht, wenns erst in C11 im Standard ist. Wir müssen strikt C89 programmieren, für alles andere gibt es in der Prüfung 0 Punkte 🙄



  • Ob dein Tutor das auch weiß?

    %lf (für double bei printf ) wird eigentlich von allen Compileren/C-Standard-Librarys akzeptiert.

    Und wie gesagt, das gilt für printf . scanf ist eine ganz andere Funktion.



  • Du meinst, ob der Professor (nicht Tutor 😉 )das weiß.

    Ja, akzeptiert wirds vielleicht schon, aber wenn es im C89 Standard offiziell eigentlich nicht drin ist, sondern erst im C11, dann DARF ich es nicht nutzen.

    Sollte ich es in der Prüfung doch nutzen (auch wenn es funktionieren würde), ist das ein Fehler und gibt Punktabzug.

    Ich darf beispielsweise auch keine Variable a einlesen und dann int array[a] schreiben und ein Array "variabler" Länge in Abhängigkeit der Variablen a zu bekommen.
    Gehen tuts schon, ist aber im C89 Standard noch nicht offiziell festgelegt --> Fehler in der Prüfung

    Aber mal kurz ne andere Frage:
    D.h. ich geb nach C89 Standard eine double Variable mit %f aus, richtig?


  • Mod

    marcm244 schrieb:

    D.h. ich geb nach C89 Standard eine double Variable mit %f aus, richtig?

    Unter anderem, ja. Es gibt noch ein paar weitere: %e, %E, %g, %G. Und noch jeweils Modifikationen dieser. Mehr findest du in Referenzen zu der Funktion.



  • marcm244 schrieb:

    ... ob der Professor (nicht Tutor 😉 ....

    Mir doch egal. 😃
    Dein Lehrmeister halt. Tja, Professoren haben leider immer recht, auch wenn man das Gegenteil schwarz auf weiß belegen kann. Wenn er der Meinung ist, das %lf für double richtig ist (denn das war schon immer so), dann versuch das Gegenteil zu beweisen.

    Irgendwo hast du auch den Schrott mit fflush(stdin); her.
    Das ist auch nicht von C89 gedeckt. Es ist aber nicht verboten, sondern gibt undefiniertes Verhalten

    marcm244 schrieb:

    Aber mal kurz ne andere Frage:
    D.h. ich geb nach C89 Standard eine double Variable mit %f aus, richtig?

    Ja, probier es aus.
    Setzte die Compilerflags für C89 -std=c89 und schalte den Warnlevel auf Maximum -Wall .
    Beseitige auch die letzte Warnung vom Compiler.

    Und schau mal in der Linkliste für Neulinge. Da stehen Links zu den Drafts der einzelnen C-Standars. Vergewissere dich selber und lies es durch (oder nur die Stellen die dich interessieren).



  • Des fflush(stdin) stand als Hinweis bei der Aufgabe dabei. Hab dann nur kurz gegoogelt, was das ist und habs davor gesetzt. Ohne das vor dem scanf() hatte ich nämlich in 2 anderen Aufgaben (wo der Hinweis dann auch stand) diverse Probleme, wenn ich irgendeine Variable öfter einlesen hab müssen.

    Ich hab grad nochmal ein paar seiner "Musterlösungen" durchgeschaut und da steht immer %f, also werd ich das nehmen. Das .txt File mit der Definition von C89 führ ich mir lieber irgendwann anders zu gemühte, weil das ist schon seeeeeeehr böse für nen Anfänger 😃

    Auf jedenfall mal Danke an euch alle!


Anmelden zum Antworten