Wann darf man was aus einer Funktion nicht returnen?



  • @EinNutzer0 sagte in Wann darf man was aus einer Funktion nicht returnen?:

    Und ich kann ja nix dafür, wenn dieses behavior, call by value result(bzw. return) heißt.

    Heißt es nicht.

    @EinNutzer0 sagte in Wann darf man was aus einer Funktion nicht returnen?:

    An welcher Stelle wird ein Parameter oder ein Rückgabewert also NICHT kopiert?

    Deine ganzen Überlegungen sind ziemlich sinnlos.

    §5.1.2.3 Program execution

    1. The semantic descriptions in this document describe the behavior of an abstract machine in which issues of optimization are irrelevant.

    Das heißt salopp gesagt: "Es muss nur dasselbe beobachtbare Verhalten dabei rauskommen. Wie ist völlig egal."
    Du bist hier im C-Forum. Hier geht es um die Sprache. Wenn Du über das Verhalten einer bestimmten Implementierung reden willst dann geh' ins Compiler- und IDE-Forum.

    @EinNutzer0 sagte in Wann darf man was aus einer Funktion nicht returnen?:

    int f1(int i)
    {
        int a = 5;
        int b = a - i;
        return b;
    }
    
    int main()
    {
        int c = 7;
        int d = f1(c);
        return d + 2;
    }
    
    int main()
    {
        return 0;
    }
    

    immer noch dasselbe. Da kannst noch so viele Verrenkungen machen (Scherze wie volatile, funktionen mit external linkage (wobei ... Interprocedural optimization) und user input mal ausgenommen.). Einen Compiler der das bei geringsten Optimierungen nicht schnallt kannst getrost in die Tonne treten.

    https://godbolt.org/z/rW64Gq

    main:
            mov     eax, 0
            ret
    

    Wie Du siehst gibt es hier nichtmal einen Funktionsaufruf. Vielleicht verstehst Du jetzt ja endlich "as-if".



  • @Swordfish sagte in Wann darf man was aus einer Funktion nicht returnen?:

    @EinNutzer0 sagte in Wann darf man was aus einer Funktion nicht returnen?:

    Und ich kann ja nix dafür, wenn dieses behavior, call by value result(bzw. return) heißt.

    Heißt es nicht.

    Bevor Du nochmal damit kommst:

    https://condor.depaul.edu/ichu/csc447/notes/wk4/ps.html

    Call by value-result

    A call by value-result, like a call by reference, requires that the argument be a variable. However, the parameters of the function or procedure are not directly bound to the variable's address. Rather, they get their own space within their own scope, and when the function or procedure is terminated, the new values of the parameters are copied back into the caller's variables. Hence, value-result differs from reference only in that the values of the caller's variables are not modified while the function or procedure is still in effect--only when it has finished.

    One advantage of calling by value-result is that the called procedure or function can safely assign to its parameters without fear of confusing side effects. (This, for example, is not true with a call by reference or by name.) On the other hand, making life easier for the callee makes life more confusing for the caller. Consider the following code:

    proc a (int x, int y) {
        x = 1;
        y = 2;
    }
    
    int t;
    a (t,t);
    print t;
    

    The value of t after calling a then depends on the order of parameter copies when the procedure call is finished.

    Soetwas gibt es weder in C noch in C++.



  • #include <stdio.h>
    
    typedef struct test_e
    {
        int i;
        char *cp;
    } Test_E;
    
    int main()
    {
        Test_E a = {5, "hallo"};
        Test_E b = a;
        printf("%d %s, %d %d %d\n", b.i, b.cp, &a == &b, &a.i == &b.i, &a.cp == &b.cp);
        printf("%p %p %p %p %p %p\n", (void *)&a, (void *)&b, (void *)&a.i, (void *)&b.i, (void *)&a.cp, (void *)&b.cp);
        return 0;
    }
    
    $ ./TestC2.out 
    5 hallo, 0 0 0
    0x7ffd9baaa950 0x7ffd9baaa940 0x7ffd9baaa950 0x7ffd9baaa940 0x7ffd9baaa958 0x7ffd9baaa948
    

    Hier erschließt sich mir Zeile 12 bis 14 und die Ausgabe überhaupt nicht... Jeder Vergleich ist falsch, und ich hätte angenommen, dass erster und dritter Vergleich true sind... Kopiert das = den kompletten Speicherbereich inkl.. Pointer einer Struktur? Würde selbiges dann auch bei einem return geschehen? Sorry, wenn sich diese Fragen für euch furchtbar anhören, aber ich möchte C (und C++) verstehen.



  • Warum sollten bei dem Vergleich die Adressen von a und b denn gleich sein (in der 3. Zeile der Ausgabe stehen diese doch)?
    Wolltest du die Inhalte vergleichen, also

    printf("%d %s, %d %d %d\n", b.i, b.cp, !memcmp(&a, &b, sizeof(Test_E)), a.i == b.i, a.cp == b.cp);
    

    ?

    PS: memcmp gibt bei "gleich" 0 zurück (daher die Negation mittels !)

    PPS: Bedenke auch, daß memcmp alle Bytes vergleicht (also auch evtl. Padding-Bytes, welche dann nicht unbedingt gleich sein müssen).



  • Also, ich habe die Ausgabe nicht manipuliert. Ich bin auch davon ausgegangen, dass &a == &b NICHT 0 liefert (zumal eine Zeile darunter unterschiedliche Adressen stehen) - aber das Gegenteil ist der Fall. Was hab ich falsch gemacht? Oder will mich der Compiler ärgern?

    Bitte beantwortet mir noch diese Frage: Was geschieht bei return a;?



  • @EinNutzer0 sagte in Wann darf man was aus einer Funktion nicht returnen?:

    Also, ich habe die Ausgabe nicht manipuliert. Ich bin auch davon ausgegangen, dass &a == &b NICHT 0 liefert (zumal eine Zeile darunter unterschiedliche Adressen stehen) - aber das Gegenteil ist der Fall. Was hab ich falsch gemacht?

    Was wird denn bei &a == &bverglichen?



  • @john-0 sagte in Wann darf man was aus einer Funktion nicht returnen?:

    Was wird denn bei &a == &bverglichen?

    Wenn ich das wüsste, dann würde ich hier nicht fragen...

    Edit: Wird der string "hallo" auch kopiert?



  • @EinNutzer0 sagte in Wann darf man was aus einer Funktion nicht returnen?:

    Wenn ich das wüsste, dann würde ich hier nicht fragen...

    Dir ist die Bedeutung des Operators & bewusst? Der liefert die Adresse einer Variablen zurück! D.h. bei &a == &b werden die Adressen der beiden Variablen verglichen und eben nicht deren Werte. Die beiden Variablen a und b liegen natürlich an unterschiedlichen Stellen auf dem Stack. D.h. solange Du hier die Speicherstellen miteinander vergleichst ist das natürlich zu erwarten, dass da Ungleichheit festgestellt wird. In C gibt es keine Möglichkeit den Operator == für struct zu überladen, d.h. a == b kann hier bei Dir nicht funktionieren. Dazu müsstest Du Dir ein Vergleichsfunktion schreiben, die dann Komponentenweise struct test_e vergleicht. Sinnvoll wäre dann der Test auf a.i == b.i, das vergleicht den Wert der beiden Integer Variablen. Für das Vergleichen von Strings gibt es die Funktion strcmp in der Standard Library.



  • Ah, ich denke, jetzt hab ich's herausgefunden:

    #include <stdio.h>
    
    typedef struct test_e
    {
        int i;
        char *cp;
    } Test_E;
    
    Test_E get_test_e()
    {
        Test_E a = {5, "hallo"};
        printf("%p\n", (void *)&a);
        printf("%p\n", (void *)a.cp);
        printf("%p\n", (void *)&(a.cp[2]));
        /*
        0x7ffd1ffb1ee0
        0x400654
        0x400656
    
        a und der Inhalt von a wird flach kopiert!
        */
        return a;
    }
    
    int main()
    {
        Test_E b = get_test_e();
        printf("%p\n", (void *)&b);
        printf("%p\n", (void *)b.cp);
        printf("%p\n", (void *)&(b.cp[2]));
        /*
        0x7ffd1ffb1f10
        0x400654
        0x400656
    
        b und der Inhalt von b wurde flach kopiert!
        */
        return 0;
    }
    

    Wieso haben char s nur so eine kurze Adresse?



  • @EinNutzer0 sagte in Wann darf man was aus einer Funktion nicht returnen?:

    Wieso haben char s nur so eine kurze Adresse?

    Der Zeiger verweist auf einen statischen Codeteil, in dem der konstante String "hallo" abgelegt worden ist. Dagegen befindet sich die Adresse von a und b auf dem Stack, der liegt üblicherweise an einer anderen Stelle im Adressraum.


Log in to reply