void funktion() und return // 2. Frage zu abs()



  • Hallo,

    ich habe zwei kleine Fragen:

    wenn ich eine beliebige Funktion mit dem Rückgabewert void habe, soll ich dann komplett auf return verzichten:

    void super_funktion(){
    ...toller Code...
    
    return; // <<- So schreiben oder komplett weglassen?!
    }
    

    Ich habe da jetzt von verschiedenen Leuten verschiedene Meinungen bekommen, aber alle ohne eine wirkliche Begründung. Wär schön wenn ihr mir da weiterhelfen könntet. Ich kriege zumindest mit Code::Blocks und dem gnu-compiler in beiden Fällen keine Warnung...ich habe bisher dazu tendiert einfach nur

    return;
    

    zu schreiben, allein schon damit ich sehe, dass da die Funktion beendet wird.

    Meine zweite Frage bezieht sich auf die Funktion abs() aus math.h

    wie genau funktioniert diese Funktion, wenn ich sie auf eine Zahl vom Typ double anwende?! Ich frage deshalb weil ich folgendes gesehen habe:

    Es wurden beliebige Zahlen von Typ double in ein Array eingelesen und sollten nur ausgegeben werden, falls es sich um eine ganze Zahl handelt:

    if( abs(array[i]) == array[i] )
            {
                printf("\n%ite Ganzzahl: %.2lf",i,array[i]);
            }
    

    jetzt würde ich gern wissen was genau passiert und wieso das eigentlich klappt.

    Was mir dabei einfällt: wie genau geht es vonstatten wenn ich eine Integer-Zahl mit einer vom typ double vergleichen will?! Kann das eigentlich gut gehen?

    Vielen Dank im voraus!

    Viele Grüße,
    chmbw



    mit "return;" am Ende finde ist besser, da du für den Fall, dass du doch mal den Rückgabetyp der Funktion von void auf was anderes änderst und du beim return den Wert vergisst anzugeben, erhältst du vom Compiler ein Fehler, statt nur eine Warnung.

    ANSI C spezifiziert

    int abs(int x);
    

    d.h. wenn du keinen int(kompatiblen) Typ übergibst, ist das Verhalten der Funktion undefiniert.



  • Wutz schrieb:

    mit "return;" am Ende finde ist besser, da du für den Fall, dass du doch mal den Rückgabetyp der Funktion von void auf was anderes änderst und du beim return den Wert vergisst anzugeben, erhältst du vom Compiler ein Fehler, statt nur eine Warnung.

    Wozu eine komplett sinnlose Anweisung angeben? Wenn ich sowas sehe, würde ich eher denken, der Programmierer hatte keine Ahnung, was er da überhaupt macht.



  • Eine Funktion gibt einen return value zurück, Standard ist int.
    Ahja, was fangen wir damit an, wenn das Dingens void ist?
    Erstmal das, was der Compiler frißt.
    ABER: Eine void- Funktion gibt NICHTS zurück, wichtig bei Interrupts usw. und deswegen sollte sie das auch formal tun, ob der Compiler das raushaut oder nicht, schlimmstenfalls gewinnst Du Performance. 😉



  • Das mit der Rückgabe würde ich so machen: 😃

    void nichts()
    {
        return (* new void());
    }
    

    Beim Vergleichen von int und double wird der int afaik in einen double umgewandelt und die beiden werden dann verglichen.

    Du kannst dir auch eine abs()-Funktion für Double schreiben (gibt's glaube ich aber auch schon mit diesem Namen)

    double fabs(double in)
    {
        return in < 0 ? -in : in;
    }
    


  • erstmal herzlichen Dank für eure Antworten!

    wenn ich also schreibe:

    double array[99];
    
    .....
    //einlesen von irgendwelchen Werten ins Array
    
    if( abs(array[i]) == array[i] )
            {
                printf("\n%ite Ganzzahl: %.2lf",i,array[i]);
            }
    

    und wie oben beschrieben schauen will obs ne Ganzzahl ist, ist das ganze mit dieser Version Mist weil abs() nur für int-werte definiert ist. ok. wenn ich jetzt aber schreibe:

    double array[99];
    
    .....
    //einlesen von irgendwelchen Werten ins Array
    
    if( array[i] == (int) array[i] )
            {
                printf("\n%ite Ganzzahl: %.2lf",i,array[i]);
            }
    

    sprich den Eintrag nach int caste und mit dem eigentlichen Wert vergleiche, ist das um einiges besser?! Eine andere Methode wüsste ich sonst nicht, bin für weitere Hinweise sehr dankbar 😉



  • chmbw schrieb:

    erstmal herzlichen Dank für eure Antworten!
    ...
    und wie oben beschrieben schauen will obs ne Ganzzahl ist, ist das ganze mit dieser Version Mist weil abs() nur für int-werte definiert ist. ok. wenn ich jetzt aber schreibe:

    double array[99];
    
    .....
    //einlesen von irgendwelchen Werten ins Array
    
    if( array[i] == (int) array[i] )
            {
                printf("\n%ite Ganzzahl: %.2lf",i,array[i]);
            }
    

    sprich den Eintrag nach int caste und mit dem eigentlichen Wert vergleiche, ist das um einiges besser?! Eine andere Methode wüsste ich sonst nicht, bin für weitere Hinweise sehr dankbar 😉

    Bei der oberen Variante wird die double-Variable zwar automatisch in einen int konvertiert, jedoch kommt bei -1.0(double) mit dem abs() 1(int) raus. Willst du nur prüfen, ob es eine Ganzzahl ist, ist die zweite Variante erstens korrekt und zweitens lesbarer.



  • abs gibts auch für double, die Funktion heißt fabs. Wenn du jedoch prüfen willst, ob eine Zahl vom Typ double ganzzahlig ist, dann sind beide Funktionen nicht das, was du suchst, denn es sind Betragsfunktionen. http://de.wikipedia.org/wiki/Betragsfunktion

    Die Funktion modf ist eher etwas für dich:

    double d = 1.1, integer, rest = modf ( d, &integer );
    	printf ( "%f %f\n", integer, rest );
    

    Oder ein cast nach int und Vergleich mit dem Ursprungswert (unsicher und nicht empfehlenswert).



  • Danke für den tollen Hinweis, ich habe mir jetzt endgültig folgende Funktion zusammengebastelt:

    #include <stdio.h>
    #include <math.h>
    
    int main()
    {
        double variable=0.0,intpart=0.0,rest=0.0;
    
        puts("zahl eingeben:");
        scanf("%lf",&variable);
    
        rest = modf(variable,&intpart);
    
        if(rest == 0.0)
        printf("\nGANZE ZAHL!!!\n");
    
        printf("Int-wert: %lf, Rest: %lf",intpart,rest);
    
        return 0;
    }
    

    Jetzt würde mich aber noch interessieren inwiefern der Cast nach int unsicher ist bzw. was genau das Problem ist. Welche Fehler können da wann auftreten?

    Viele Grüße



  • Beim Casten können Informationen verloren gehen. Das ist aber nur der Fall, sofern der Typ gecstete Typ kleiner ist. Beispiel:

    double x = 2.64159;
    
    int a = (int) x; // a = 2
    

    Nochmal zu der Sache mit dem return. Wie der Name sagt, dient es dazu eine Funktion zu beenden. Dabei hat es einen Grund, warum return auch bei void-Funktionen möglich ist.

    void update(int *x, int size)
    {
     if (size == 0) // bei 0 gehts net
     {
      return; // Funktion vorzeitig beenden
     }
    }
    


  • Hi,

    dass generell Informationsverlust auftreten kann ist mir klar, aber ich habe ja gecastet um nur die Vorkommazahl für den Vergleich zu erhalten, sprich den Informationsverlust bewusst in Kauf genommen, und die gecastete Zahl wird ja auch nur zum Zwecke des Vergleichs verwendet. Klar, modf ist um einiges eleganter, aber so ganz klar ist mir noch immer nicht was Big Brother mit unsicher auf meine if-Bedingung bezogen meinte.

    Bezüglich dem return:

    ich habe für mich aus den Beiträgen jetzt folgendes herausgezogen: ich verwende am Ende einer void-Funktion KEIN return. Return sollte in void-Funktionen AUSSCHLIEßLICH zum VORZEITIGEN verlassen verwendet werden. Hoffe das stimmt so. 😉

    Viele Grüße und vielen Dank,

    chmbw



  • chmbw schrieb:

    Hi,

    dass generell Informationsverlust auftreten kann ist mir klar, aber ich habe ja gecastet um nur die Vorkommazahl für den Vergleich zu erhalten, sprich den Informationsverlust bewusst in Kauf genommen, und die gecastete Zahl wird ja auch nur zum Zwecke des Vergleichs verwendet. Klar, modf ist um einiges eleganter, aber so ganz klar ist mir noch immer nicht was Big Brother mit unsicher auf meine if-Bedingung bezogen meinte.

    Bezüglich dem return:

    ich habe für mich aus den Beiträgen jetzt folgendes herausgezogen: ich verwende am Ende einer void-Funktion KEIN return. Return sollte in void-Funktionen AUSSCHLIEßLICH zum VORZEITIGEN verlassen verwendet werden. Hoffe das stimmt so. 😉

    Viele Grüße und vielen Dank,

    chmbw

    Bezüglich der Unsicherheit: Der Computer stellt Dezimalzahlen durch die FPU (Floating Point Unit) in Exponentialschreibweise dar.
    Es kann daher vorkommen, dass eine Zahl anders dargestellt wird eine scheinbar gleiche.

    Aufgrund der unterschiedlichen Darstellung kann es also sein, dass ein Vergleich auf false hinausläuft, obwohl die Zahl scheinbar gleich ist.

    Darauf wollte man dich wohl hinweisen. Der Computer kann speichertechnisch einfach keine 100.000.000 Nachkommastellen erfassen und man versucht sich daher so zu helfen.

    Lösen kann man das Problem in dem man einen Schwellwert verwendet. Sollte die Zahl nicht um +0.00005 oder -0.00005 (Beispiel) abweichen, so ist sie als gleich anzusehen.

    Bezüglich des Returns:
    Exakt. 👍



  • chmbw schrieb:

    Hi,

    dass generell Informationsverlust auftreten kann ist mir klar, aber ich habe ja gecastet um nur die Vorkommazahl für den Vergleich zu erhalten, sprich den Informationsverlust bewusst in Kauf genommen, und die gecastete Zahl wird ja auch nur zum Zwecke des Vergleichs verwendet. Klar, modf ist um einiges eleganter, aber so ganz klar ist mir noch immer nicht was Big Brother mit unsicher auf meine if-Bedingung bezogen meinte.

    Wurde ja prizipiell schon genannt. Eine double Zahl x kann größer als INT_MAX sein.
    Es sein nun x > INT_MAX. Nun castest du nach int: (int)x
    Wie soll das der Compiler konvertieren? Passt nicht. Das Ergebnis ist nicht definiert.



  • Habt vielen Dank, wieder einiges gelernt 🙂

    Danke!


Log in to reply