Frage zu Zeiger in Funktion(int*)



  • Hallo liebe Community,

    ihr konntet mir bisher immer super helfen.

    Nun habe ich wieder eine Verständnisfrage zu folgendem Code:

    #include <iostream>
    using namespace std;
    void funktion (int* zahl2) //was wird in diese Funktion eingegeben, bzw. wie läuft diese ab? Ich habe auch mal probiert den * wegzu lassen. 
    {
    cout << "Adresse zahl2: " << &zahl2 << endl; //wo wird diese variable gespeichert? Ich habe diese nicht deklariert. Laut cout, muss das immernoch zahl1 sein.
    *zahl2 *= 2; // diese Rechenoperation verstehe ich nicht. Ich habe die Variable nicht deklariert, aber diese wird später benutzt.
    } int main ()
    {
    int zahl1 = 5;
    cout << "Zahl1 vor der Funktion: " << zahl1 << endl;
    cout << "Adresse: " << &zahl1 << endl;
    funktion (&zahl1); //Müssen an Pointer grundsätzlich Adressen übergeben werden?
    cout << "Zahl1 nach der Funktion: " << zahl1 << endl;
    }
    

    was genau macht die void funktion?
    Was wird an diese Funktion übergeben?
    Wird hier automatisch ein neuer Übergabeparameter in Form eines Pointers angelegt, mit dem namen zahl2?
    Ist das dann hier eine Art Doppelpointer? Da bei cout ja immer noch zahl1 steht.
    Vielen Dank für eure Hilfe!!


  • Mod

    Ich habe Zweifel, das dein Kommentar zur Zeile 5 stimmt: https://ideone.com/qeqg14
    Und damit bricht deine gesamte Fragestellung zusammen.

    Du hast zwei Variablen: zahl1, ein Integer, lebt in der mein, definiert in Zeile 9. zahl2 ein Zeiger auf Integer, lebt in der funktion, definiert in Zeile 3. zahl1 wird in Zeile 9 der Wert 5 (ein Integer) zugewiesen. zahl2 wird durch den Aufruf in Zeile 12 für diesen Aufruf der Wert &zahl1 zugewiesen. Somit ist zahl2 für den Durchlauf von funktion ein Zeiger auf zahl1.

    Zeiger (auf egal was) nehmen als Wert die Adresse von anderen Variablen an. Sie sind aber selber auch Variablen, und haben selber auch Adressen. In Zeile 12 gibst du die Adresse von zahl1 aus, in Zeile 5 die Adresse von zahl2. Wenn du noch eine Ausgabe des Wertes von zahl2 einfügen würdest, würdest du sehen, dass dieser Wert gleich der Adresse von zahl1 ist.



  • @bthight

    void funktion (int* zahl2) //was wird in diese Funktion eingegeben, bzw. wie läuft diese ab? Ich habe auch mal probiert den * wegzu lassen.

    Das ist eine Funktion mit dem Namen (Bezeichner) funktion. Diese hat als einzigen Parameter einen Zeiger auf int
    { cout << "Adresse zahl2: " << &zahl2 << endl; //wo wird diese variable gespeichert? Ich habe diese nicht deklariert. Laut cout, muss das immernoch zahl1 sein.
    Alle Variablen aus der Parameterliste einer Funktion sind lokal zu dieser Funktion. Da du aber den Inhalt von der Adresse, auf die zahl2 zeigt, ausgibst, siehst du den Wert von zahl1.

    *zahl2 *= 2; // diese Rechenoperation verstehe ich nicht. Ich habe die Variable nicht deklariert, aber diese wird später benutzt.
    Das ist (*zahl2) = (*zahl2) * 2; Der * vor dem Variablennamen ist der Dereferenzierungsoperator.
    Die ist deklariert. Sogar definiert. In der Parameterliste.
    }

    //Müssen an Pointer grundsätzlich Adressen übergeben werden?

    Dafür sind sie gemacht. Wenn du es anders machst, handelst du dir nur Schwierigkeiten ein.



  • @manni66 sagte in Zeiger mit Inkrement auf Array:

    @bthight sagte in Zeiger mit Inkrement auf Array:

    C++ Programmieren für Einsteiger von Michael Bonacina.

    Der Mann ist noch schlimmer als Jürgen Wolf. Der kann nicht nur Bücher für zig verschiedene Sprachen und Themen schreiben - nein, nebenbei leitet er auch noch den Verlag.

    Buch => Altpapiertonne

    Das war ernst gemeint



  • @manni66 sagte in Frage zu Zeiger in Funktion(int*):

    @manni66 sagte in Zeiger mit Inkrement auf Array:

    @bthight sagte in Zeiger mit Inkrement auf Array:

    C++ Programmieren für Einsteiger von Michael Bonacina.

    Der Mann ist noch schlimmer als Jürgen Wolf. Der kann nicht nur Bücher für zig verschiedene Sprachen und Themen schreiben - nein, nebenbei leitet er auch noch den Verlag.

    Buch => Altpapiertonne

    Das war ernst gemeint

    Das stammt aus dem Buch. Das stimmt.



  • Danke für eure Antworten.

    Ich verstehe, dass man einem Zeiger eine Adresse zuweisen muss, irgendwie logisch. Sozusagen eine direkte Verbindung von A nach B.

    Diese wird über & zugewiesen.
    Über das * kann man den Wert der auf der Adresse steht direkt verändern.

    Bloß die Void Funktion im Buchspiel finde ich merkwürdig.

    Man springt aus dem bisherigen Code raus, mit einem neuen Zeiger auf einen Int. Dieser Zeiger bekommt die Adresse der zahl1 zugewiesen.

    —> intuitiv hätte ich gedacht bei einem erwarteten Zeiger bei Void funktion (int* zahl2), kommt auch ein Zeiger rein. Keine Adresse.

    Mit dem Zeiger manipuliere ich also direkt den hinter der Adresse von zahl1 Stehenden Wert?



  • @bthight sagte in Frage zu Zeiger in Funktion(int*):

    intuitiv hätte ich gedacht bei einem erwarteten Zeiger bei Void funktion (int* zahl2), kommt auch ein Zeiger rein. Keine Adresse.

    Irgendwo muss ja mal ein Wert für einen Zeiger herkommen.
    „Normalen“ Variablen kannst du doch auch direkt Werte zuweisen.

    Mit dem Zeiger manipuliere ich also direkt den hinter der Adresse von zahl1 Stehenden Wert?
    Ja, damit hast du eine Referenz auf diese Variable.

    Du kannst aber auch den Zeiger manipulieren, dann zeigt er woanders hin.



  • @bthight sagte in Frage zu Zeiger in Funktion(int*):

    Bloß die Void Funktion im Buchspiel finde ich merkwürdig.

    Was erwartest du von Lehrbeispielen?

    Die sollen einfach sein und das wesentliche zeigen.
    Für komplexere Dinge fehlt auch noch weiteres Wissen.



  • @DirkB sagte in Frage zu Zeiger in Funktion(int*):

    @bthight sagte in Frage zu Zeiger in Funktion(int*):

    Bloß die Void Funktion im Buchspiel finde ich merkwürdig.

    Was erwartest du von Lehrbeispielen?

    Die sollen einfach sein und das wesentliche zeigen.
    Für komplexere Dinge fehlt auch noch weiteres Wissen.

    Ich hätte erwartet, dass wenn noch nie ein Zeiger irgendwo hin übergeben wird, dass in der Funktion der Übergabeparameter ein Zeiger ist, und nicht eine anderes lautende Variable, als Adresse eingegeben wird.

    Mir hätte hier eine langsamere Herangehensweise gefallen. Aber wie gesagt, ich bin Anfänger.



  • @bthight sagte in Frage zu Zeiger in Funktion(int*):

    dass in der Funktion der Übergabeparameter ein Zeiger ist,

    in der Funktion ist es ein Zeiger.

    und nicht eine anderes lautende Variable, als Adresse eingegeben wird.

    Da hast du gleich den Adressoperator genutzt/kennen gelernt.

    Da du noch am Anfang bist, ist die einzige Möglichkeit eine gültige Adresse zu bekommen, die von einem vorhandenen Objekt (Variable) zu nehmen.


  • Mod

    Vergiss mal die Funktion, anderes ist hier viel wichtiger. Verstehst du folgenden Code komplett? Kannst du von jeder Zeile ohne zu zögern genau sagen, was sie warum macht? Ganz ehrlich? Denn das ist hier das was wichtig ist.

    #include <iostream>
    using namespace std;
    int main ()
    {
        int zahl1 = 5;
        cout << "Wert Zahl1 am Anfang: " << zahl1 << endl;
        cout << "Adresse zahl1 am Anfang: " << &zahl1 << endl;
    
        int* zahl2 = &zahl1;
        cout << "Wert Zahl2 am Anfang: " << zahl2 << endl;
        cout << "Adresse zahl2  am Anfang: " << &zahl2 << endl;
    
       *zahl2 *= 2;
        cout << "Wert Zahl1 am Ende: " << zahl1 << endl;
        cout << "Adresse zahl1  am Ende: " << &zahl1 << endl;
        // cout << "Wert Zahl2 am Ende: " << zahl2 << endl;
        // cout << "Adresse zahl2  am Ende: " << &zahl2 << endl;
    }
    

    Zweite Aufgabe: Kannst du vorhersagen, was die beiden auskommentierten Zeilen am Ende ausgeben würden, ohne es auszuprobieren?



  • @SeppJ sagte in Frage zu Zeiger in Funktion(int*):

    zahl2

    Also ohne es auszuprobieren würde ich folgenden Output an Zahlen erwarten:

    5
    0xirgendwas

    5
    0xirgendwas

    10 --> durch den Pointer von Zahl 2, auf die Adresse von 1, und der Multiplikation mit 2.

    Zahl 2, dort erwarte ich wieder 10, weil die Zahl zwei zeigt durch den Pointer direkt auf die Adresse von Zahl 1 und ändert den Wert um den Faktor 2.

    0xirgendwas

    Soweit zu meinem Logikverständnis. Ich hoffe ich blamiere mich nicht.


  • Mod

    Leider nicht. Du hast Zeiger nicht verstanden. Liegt vielleicht auch an der grausamen Namensgebung der Variablen aus deinem Beispiel (Siehe auch ganz dringend manni66s Ratschlag!). zahl2 ist nämlich keine Zahl. Es ist eine Wegbeschreibung, wo eine andere Zahl zu finden ist.



  • @SeppJ sagte in Frage zu Zeiger in Funktion(int*):

    Leider nicht. Du hast Zeiger nicht verstanden. Liegt vielleicht auch an der grausamen Namensgebung der Variablen aus deinem Beispiel (Siehe auch ganz dringend manni66s Ratschlag!). zahl2 ist nämlich keine Zahl. Es ist eine Wegbeschreibung, wo eine andere Zahl zu finden ist.

    Vielen lieben Dank für deine Mühen.
    Ich werde mir ein neues Buch zulegen müssen.



  • @bthight
    Bei int *zahl2; ist zahl2 ein Pointer und *zahl2 ein int (so wie in der Definition steht)
    Ein Pointer ist eine Variable, die eine Adresse von einem Objekt aufnimmt.

    Wenn du nur den Variablennamen angibst, bekommst du den Inhalt dieser Variablen (also die Adresse)
    Mit dem Dereferenzierungsoperator * bekommst du den Inhalt an dieser Adresse.
    Und da ein Pointer eine Variable ist, hat er auch selber einen Speicherplatz, den man mit dem Adressoperator & bekommen kann.

    Es spielt bei der Definition aber keine Rolle, wo der * steht.

    int *zahl2;
    int * zahl2;
    int* zahl2;
    

    Ist alles identisch zahl2 ist ein Pointer auf int

    Unübersichtlich wird es erst, wenn du mehrere Variablen definiierst

    int *zahl2, zahl1;
    int * zahl2, zahl1;
    int* zahl2, zahl1;
    

    Ist auch alles identisch zahl2 ist ein Pointer auf int und zahl1 ist ein int ( auch wenn Zeile 3 etwas anderes vorgaukelt)

    Wert Zahl1 am Anfang: 5 
    Adresse zahl1 am Anfang: 0x4711   (ausgedacht)
    Wert Zahl2 am Anfang:  0x4711     <-- Inhalt von zahl2 ist die Adresse von zahl1
    Adresse zahl2 am Anfang: 0x0815   <-- zahl2 hat eine eigene Adresse
    


  • Ungerade Adressen bei int-Zeigern? duck und weg...



  • @Th69 sagte in Frage zu Zeiger in Funktion(int*):

    Ungerade Adressen bei int-Zeigern? duck und weg...

    Auf einem 8-Bit System ....



  • @DirkB sagte in Frage zu Zeiger in Funktion(int*):

    @Th69 sagte in Frage zu Zeiger in Funktion(int*):

    Ungerade Adressen bei int-Zeigern? duck und weg...

    Auf einem 8-Bit System ....

    https://godbolt.org/z/ojToff 😉



  • @Th69 sagte in Frage zu Zeiger in Funktion(int*):

    Ungerade Adressen bei int-Zeigern? duck und weg...

    Das ging auch bei einem 68020 problemlos, aber nur für Peripherie.


Log in to reply