Warum hier Doppel-Pointer?


  • Mod

    SeppJ schrieb:

    Also ich als Prof würde euch alle durchfallen lassen, wenn ihr mir damit kämt, dass das nicht call by reference wäre. Ihr habt ganz klar nicht verstanden (oder eher: Ihr stellt euch extra dumm, um vermeintlich gebildet auszusehen), was der konzeptionelle Unterschied zwischen call by value und call by reference ist. Das sind Programmierkonzepte, und keine Frage der genauen technischen Umsetzung.

    SeppJ schrieb:

    Wenn der Programmierer einer C-Funktion einen Zeiger auf einen Wert anstatt dem Wert selbst erwartet und den Wert über diesen Zeiger ändert, dann hat er den Zeigerparameter ganz klar als Referenz auf diesen Wert benutzt und es ist vollkommen egal, dass der Zeiger selber kopiert wurde oder nicht. C ist bloß eben sehr explizit in seiner Syntax und man sieht die nackten Zeiger, die vor einem in anderen Sprachen versteckt werden. Trotzdem ist es in C möglich, dass man Funktionen programmieren kann, die das Konzept 'call by reference' umsetzen, um mit der Außenwelt zu kommunizieren. Ob sie das manuell über value-kopierte Pointer simulieren oder ob die Sprache extra Syntaxzucker dafür anbietet, ändert nichts da dran.

    Richtig, aber was du hier ansprichst ist eben nicht technische Umsetzung, sondern Anwendung oder Nutzung eines Mechanismuses, insofern ist dein Argument keine Konkretisierung der Behauptung oben.

    SeppJ schrieb:

    Das ist vergleichbar damit, wenn Leute behaupten, in C könne man nicht objektorientiert programmieren, weil es keine direkte Unterstützung in der Sprache dafür gibt. Dabei sind die Leute, die sich hier so sehr an dem Begriff 'Referenz' aufhängen, normalerweise die ersten, die angesprungen kommen, wenn mal wieder ein Anfänger behauptet, objektorientiert ginge nicht in C.

    Wiederum sehe die Verbindung nicht: es geht nicht darum, ob die Unterscheidung zwischen call-by-value und call-by-reference im Großen und Ganzen wichtig für die Programmierung ist, sondern was mit diesen Begriffen überhaupt gemeint sein soll. Zweifellos wirst du nicht behaupten wollen, dass präzise Sprache unwesentlich ist.

    Bashar schrieb:

    Call-by-reference bedeutet nicht, dass eine Referenz übergeben wird, sondern dass das Argument per Referenz übergeben wird. Wenn das Argument zufällig eine Art von Referenz ist, wird aus Call-by-value nicht auf magische Weise Call-by-reference.

    Um es vielleicht noch mehr auf den Punkt zu bringen: es geht bei der Begrifflichkeit call-by-X nicht darum, was für eine Art Entität formale Parameter sind, sondern um deren Beziehung zum tatsächlichen Funktionsargument bei der Auswertung eines Funktionsaufrufes.
    Wikipedia sagt es hier recht gut (wobei ich mir in dem Artikel mehr Quellen wünschen würde):

    Call by reference can be simulated in languages that use call by value and don't exactly support call by reference, by making use of references (objects that refer to other objects), such as pointers (objects representing the memory addresses of other objects). Languages such as C and ML use this technique. It is not a separate evaluation strategy—the language calls by value—but sometimes it is referred to as call by address (also referred to as pass by address).

    Wenn etwas nur simuliert wird, dann ist es eben trotzdem nicht das gleiche Ding.


  • Mod

    Nehmen wir an, ich erfinde eine Sprache, bei der "echtes" Call-by-reference dadurch erreicht wird, dass man überall ein * vor die Variable schreiben muss. Ähnlich wie & für Referenzen in C++, außer dass die Regel der Sprache vorschreibt, dass der * zum Namen gehört und bei Benutzung daher auch drangeschrieben werden muss. Wäre es dann call-by-reference nach eurer Definition? Ja. Was soll also diese willkürliche Trennung zu C-Funktionen, bei denen man freiwillig überall * vor eine Variable schreibt?

    Bashar schrieb:

    Call-by-reference bedeutet nicht, dass eine Referenz übergeben wird, sondern dass das Argument per Referenz übergeben wird. Wenn das Argument zufällig eine Art von Referenz ist, wird aus Call-by-value nicht auf magische Weise Call-by-reference.

    Wieso nicht? Bei Sprachen mit nach deiner Definition "echtem" call-by-reference wird schließlich die Referenz kopiert. Es ist exakt das gleiche wie der Mechanismus in C. Nur weil die Syntax etwas anders aussieht ist es auf magische Weise auf einmal ein anderer Mechanismus?


  • Mod

    SeppJ schrieb:

    Nehmen wir an, ich erfinde eine Sprache, bei der "echtes" Call-by-reference dadurch erreicht wird, dass man überall ein * vor die Variable schreiben muss. Ähnlich wie & für Referenzen in C++, außer dass die Regel der Sprache vorschreibt, dass der * zum Namen gehört und bei Benutzung daher auch drangeschrieben werden muss. Wäre es dann call-by-reference nach eurer Definition? Ja. Was soll also diese willkürliche Trennung zu C-Funktionen, bei denen man freiwillig überall * vor eine Variable schreibt?

    Entscheidend ist, wie der Aufruf aussieht. Nehmen wir einfach mal das Code-Beispiel von dem oben verlinkten Wikipedia-Artikel:

    void modify(int p, int* q, int* r) {
        p = 27; // passed by value: only the local parameter is modified
        *q = 27; // passed by value or reference, check call site to determine which
        *r = 27; // passed by value or reference, check call site to determine which
    }
    
    int main() {
        int a = 1;
        int b = 1;
        int x = 1;
        int* c = &x;
        modify(a, &b, c); // a is passed by value, b is passed by reference by creating a pointer (call by value),
                        // c is a pointer passed by value
                        // b and x are changed
        return 0;
    }
    

    Der Kommentar "b is passed by reference by creating a pointer (call by value)" könnte besser sein. Wesentlich ist, dass der Anwender beim Aufruf modify(a, &b, c) sein Programm ändern musste: es wird eben nicht b übergeben, sondern ein Zeiger auf b - dass auf einer höheren Abstraktionsebene b der eigentliche Gegenstand der Programmlogik sein soll, ergibt sich nicht aus der Syntax und ist keine Funktion der Sprache selbst. Es ist passing a reference by value.



  • der duden klärt das ganze an und für sich auch ganz gut auf:

    [quote=https://www.duden.de/rechtschreibung/Referenz]
    Person oder Stelle, auf die verwiesen wird, weil sie [lobende] Auskunft über jemanden geben kann
    [/quote]

    [quote=https://www.duden.de/rechtschreibung/Wert]
    in Zahlen oder Zeichen ausgedrücktes Ergebnis einer Messung, Untersuchung o. Ä.; Zahlenwert
    [/quote]

    jedenfalls bedeutet call bei value doch, dass eine kopie (vom objekt, von der variable, usw) erstellt wird, und call by reference dass eben keine kopie erstellt, sondern auf eine entsprechende stelle im speicher verwiesen wird.


  • Mod

    camper schrieb:

    Es ist passing a reference by value.

    Wenn du siehst, wie der Trick des Magiers auf der Bühne funktioniert, ist es ein Zauberkunststück, und wenn nicht ist es für dich echte Magie?


  • Mod

    SeppJ schrieb:

    camper schrieb:

    Es ist passing a reference by value.

    Wenn du siehst, wie der Trick des Magiers auf der Bühne funktioniert, ist es ein Zauberkunststück, und wenn nicht ist es für dich echte Magie?

    Kommt auf den Trick an. Wenn ich den Trick sehe und verstehe, weiss ich, dass es keine Magie ist, andernfalls kann Magie jedenfalls nicht kategorisch ausgeschlossen werden.

    Wir verstehen bereits, dass in C Zeiger by value übergeben werden; das plötzlich als etwas Anderes, dass dieser Erkenntnis widerspricht, zu bezeichnen - nur weil auf einer anderen Ebene nicht am Zeiger als solchen interessiert sind, entwertet die Begrifflichkeiten.


  • Mod

    Ich meine eher umgekehrt: Bloß weil du in den anderen Sprachen den Trick nicht siehst, C aber mit offenen Karten spielt, ist es auf einmal ein anderer Mechanismus, wenn beide doch das gleiche machen?

    camper schrieb:

    Wir verstehen bereits, dass in C Zeiger by value übergeben werden; das plötzlich als etwas Anderes, dass dieser Erkenntnis widerspricht, zu bezeichnen - nur weil auf einer anderen Ebene nicht am Zeiger als solchen interessiert sind, entwertet die Begrifflichkeiten.

    Es geht aber nicht darum, dass der Zeiger kopiert wird, sondern dass dieser Zeiger eine Referenz darstellt. Das Objekt meiner Begierde wird also per Referenz übergeben!



  • camper schrieb:

    Es ist passing a reference by value.

    wtf? es wird doch eine referenz auf b übergeben. ob das ding nachher q, value, pusemuckel heißt, ist doch egal. es bleibt eine referenz auf b. 😕



  • SeppJ schrieb:

    Nehmen wir an, ich erfinde eine Sprache, bei der "echtes" Call-by-reference dadurch erreicht wird, dass man überall ein * vor die Variable schreiben muss. Ähnlich wie & für Referenzen in C++, außer dass die Regel der Sprache vorschreibt, dass der * zum Namen gehört und bei Benutzung daher auch drangeschrieben werden muss. Wäre es dann call-by-reference nach eurer Definition? Ja. Was soll also diese willkürliche Trennung zu C-Funktionen, bei denen man freiwillig überall * vor eine Variable schreibt?

    Also erstmal ist das nicht meine oder unsere Definition, sondern eine historisch etablierte Definition. Meines Wissens war das in Fortran so, dass alle Argumente per Referenz übergeben wurden, und es gab eben auch andere Strategien, wie Call-by-value und Call-by-name. Später konnte man (z.B. in Pascal mit VAR) einzelne Parameter zu Referenzparametern erklären und hat damit im Prinzip eine Mischung produziert bzw. den Begriff "Call-by-X" von der Funktion auf das Argument reduziert (und hätte ihn dabei in "Pass-by-X" ändern müssen.) Dann kam C++ und hat der "Referenz" eine eigenständige Existenz außerhalb von Funktionsparametern zugeteilt, wenn auch ohne echten First-Class-Status, man kann ja bspw. Referenzen nicht zuweisen oder ihre Adresse ermitteln.

    Dein fiktives Beispiel wirft die Frage auf, was der Parameter ohne * bedeutet, aber noch viel wichtiger, wie der Aufruf aussieht. Dazu hat Camper schon was geschrieben.

    Bashar schrieb:

    Call-by-reference bedeutet nicht, dass eine Referenz übergeben wird, sondern dass das Argument per Referenz übergeben wird. Wenn das Argument zufällig eine Art von Referenz ist, wird aus Call-by-value nicht auf magische Weise Call-by-reference.

    Wieso nicht? Bei Sprachen mit nach deiner Definition "echtem" call-by-reference wird schließlich die Referenz kopiert. Es ist exakt das gleiche wie der Mechanismus in C. Nur weil die Syntax etwas anders aussieht ist es auf magische Weise auf einmal ein anderer Mechanismus?

    "Die Referenz wird kopiert" hat semantisch überhaupt keine Bedeutung. Das ist ein Implementationsdetail.

    Kann es sein, dass du zwischen nebulösen "Programmierkonzepten", wozu sowas wie OOP in C gehört, und "Mechanismen", also Implementationsdetails, keinen Raum zulässt?


  • Mod

    Wade1234 schrieb:

    camper schrieb:

    Es ist passing a reference by value.

    wtf? es wird doch eine referenz auf b übergeben. ob das ding nachher q, value, pusemuckel heißt, ist doch egal. es bleibt eine referenz auf b. 😕

    Ja? Du sagst es ja selber: es wird eine Referenz (ein C-Zeiger) auf b übergeben, und nicht b selbst.


  • Mod

    camper schrieb:

    Wade1234 schrieb:

    camper schrieb:

    Es ist passing a reference by value.

    wtf? es wird doch eine referenz auf b übergeben. ob das ding nachher q, value, pusemuckel heißt, ist doch egal. es bleibt eine referenz auf b. 😕

    Ja? Du sagst es ja selber: es wird eine Referenz (ein C-Zeiger) auf b übergeben, und nicht b selbst.

    Aber das ist doch die Definition dafür, dass b bei Reference gecalled wird!



  • ja genau das ist doch "call by reference", duden referenz: "stelle, auf die verwiesen wird".


  • Mod

    SeppJ schrieb:

    camper schrieb:

    Wade1234 schrieb:

    camper schrieb:

    Es ist passing a reference by value.

    wtf? es wird doch eine referenz auf b übergeben. ob das ding nachher q, value, pusemuckel heißt, ist doch egal. es bleibt eine referenz auf b. 😕

    Ja? Du sagst es ja selber: es wird eine Referenz (ein C-Zeiger) auf b übergeben, und nicht b selbst.

    Aber das ist doch die Definition dafür, dass b bei Reference gecalled wird!

    Wie oben geschrieben, geht es nicht um die Art Entität, die übergeben wird, sondern um die Beziehung zwischen tatsächlichem Argument und formalem Parameter.

    In

    void modify(int p, int* q, int* r);
    modify(a, &b, c);
    

    ist das tatsächliche Argument &b bereits ein Zeiger (also eine Referenz im allgemeineren Sinn) auf b. Der zugehörige formale Parameter q ist nach diesem Aufruf ebenfalls eine (unabhängige) Referenz auf b - also eine Kopie des tatsächlichen Arguments &b, ergo call-by-value. Um call-by-reference zu erhalten, müsste q in einer Referenzbeziehung zu &b stehen. Das ist aber nicht der Fall. &b ist nicht einmal ein Objekt. Und irgendwelche Änderungen von q innerhalb der modify-Funktion haben keinerlei Auswirkung auf das Argument &b, die Adresse von b ist ja nicht modifizierbar.


  • Mod

    Das ist doch bei Programmiersprachen, die 'echtes' call-by-reference bieten genauso, der einzige Unterschied liegt in der Syntax, die diese Komplexität vor dir versteckt.

    Möchtest du auch behaupten, die Engländer kennen nicht das Konzept des "Besitz", weil die Syntax ihrer Sprache keinen Genitiv kennt? Schließlich werden Besitzverhältnisse nur mit Apostroph-s 'simuliert'.


  • Mod

    SeppJ schrieb:

    Das ist doch bei Programmiersprachen, die 'echtes' call-by-reference bieten genauso, der einzige Unterschied liegt in der Syntax, die diese Komplexität vor dir versteckt.

    Das kann man natürlich so sehen, aber wieso bist du der Meinung, dieser Unterschied wäre völlig bedeutungslos? Nach deiner Logik sind etwa Klassifizierungen von Programmiersprachen als etwa imperativ, funktional, objektorientiert u.ä. sinnlos, solange sie alle Turing-complete sind, kann sowieso jedes Programm in jeder dieser Sprachen existieren - und diese Programme unterscheiden sich dann bloß in ihrem Quelltext, also (auch) der Syntax.

    SeppJ schrieb:

    Möchtest du auch behaupten, die Engländer kennen nicht das Konzept des "Besitz", weil die Syntax ihrer Sprache keinen Genitiv kennt? Schließlich werden Besitzverhältnisse nur mit Apostroph-s 'simuliert'.

    Keineswegs. Wir sind uns aber einig, dass sie keinen Genitiv haben. Die Tatsache, dass ein Konstrukt existiert, das dessen Funktion übernimmt, ändert das nicht.


  • Mod

    camper schrieb:

    SeppJ schrieb:

    Das ist doch bei Programmiersprachen, die 'echtes' call-by-reference bieten genauso, der einzige Unterschied liegt in der Syntax, die diese Komplexität vor dir versteckt.

    Das kann man natürlich so sehen, aber wieso bist du der Meinung, dieser Unterschied wäre völlig bedeutungslos? Nach deiner Logik sind etwa Klassifizierungen von Programmiersprachen als etwa imperativ, funktional, objektorientiert

    Lustig, denn genau das Beispiel hatte ich ja schon gebracht. Wenn hier im Forum jemand behauptet, in C könne man nicht objektorientiert programmieren, wird er ausgelacht. Aber C hat keinerlei eingebaute Unterstützung für Objektorientierung. Alles entspringt der Art und Weise, wie der Programmierer über seine Algorithmen und Datenstrukturen denkt, bevor er diese Entwürfe dann mit Structs und Funktionen simuliert.

    Wo ist da jetzt der Unterschied zu Call-by-reference?


  • Mod

    SeppJ schrieb:

    Wo ist da jetzt der Unterschied zu Call-by-reference?

    Unter anderem der, dass Objektorientierung kein besonders scharfer Begriff ist, der an einen einzelnen Mechanismus gekoppelt ist. Objektorientiert zu programmieren heisst ja gerade nicht (zwingend), bestimmte Sprachfeatures auszunutzen (wobei letzteres nat. naheliegt, wenn sie existieren).
    Call-by-reference bezeichnet (etabliert) hingegen einen bestimmten Mechanismus, wie Funktionsaufrufe ausgewertet werden - die Ausnutzung dieses Mechanismusses ebenso als call-by-reference zu bezeichnen, wäre logisch - die Anwendung eines anderen Mechanismusses auf eine Weise, die einen gleichartigen Effekt erziehlt, heisst dagegen besser anders, andernfalls wird die Sprache verwirrend und mehrdeutig.
    Wenn man den Zusammenhang nicht kennt, ist es naheliegend, zu glauben, call-by-reference hieße, Funktionen mit Referenzen aufzurufen. Das ist aber eben nicht der Fall, und Erfindung eigenen Vokabulars (auch wenn in sich konsistent) der Kommunikation nicht unbedingt dienlich.


Anmelden zum Antworten