Pointer und Reference



  • Das wichtigste dazu wurde aber noch nicht gesagt. Übergibt man ein Array an eine Funktion

    void foo(char* arr);
    

    oder

    void bar(char arr[]);
    

    , dann geht die Information über die Länge des Arrays verloren! http://ideone.com/NBqtR

    2 Möglichkeiten gibt es, um das Problem zu lösen:

    1.)Eine Referenz auf das Array übergeben. Dies ist die unleserliche, komplizierte Variante: http://ideone.com/elCPx

    2.)Einen Container deiner Wahl nehmen, der Ersatz für ein Array heißt std::tr1::array (bzw std::array, wenn du unter C++0x bist). Findet sich im Header <array>.
    Verwendung: http://ideone.com/ArtD2

    Wenn du einen dynamischen Container brauchst, dann ein std::vector.

    Variante 2 ist eigentlich immer zu bevorzugen!



  • Hallo!

    Ich habe noch eine Frage:

    Auf der ersten Seite stand ja folgendes (manni) hat das geschrieben:

    Tom83 schrieb:

    Wie kann man denn rausfinden ob schon ein Zeiger angelegt wurde?

    Das kann man nicht herausfinden. Du kannst nur testen, ob ein Pointer kein 0-Zeiger ist. Dazu musst du natürlich dein Array erst mal mit 0 initialisieren:
    C/C++ Code:
    Saeugetier *s1[10] = {};
    C/C++ Code:
    Saeugetier *s1[10] = {};
    C/C++ Code:
    Saeugetier *s1[10] = {};

    Anschließend kannst du dann prüfen:
    C/C++ Code:
    bool pruef (Saeugetier s) {
    cout << "speicherbereich verweist auf:" << (void
    )s;

    if (s == 0) {
    C/C++ Code:
    bool pruef (Saeugetier s) {
    cout << "speicherbereich verweist auf:" << (void
    )s;

    if (s == 0) {
    C/C++ Code:
    bool pruef (Saeugetier s) {
    cout << "speicherbereich verweist auf:" << (void
    )s;

    if (s == 0) {

    Die Funktion wird jetzt natürlich anders aufgerufen:
    C/C++ Code:
    flag = test->pruef(s1[i]);
    C/C++ Code:
    flag = test->pruef(s1[i]);
    C/C++ Code:
    flag = test->pruef(s1[i]);

    Die Methode

    bool pruef (Saeugetier *s)
    

    funktioniert auch so:

    bool pruef (Saeugetier s[])
    

    Warum ist dass denn so? Meine Vermutung: Das Array ist ja an sich eh schon ein Zeiger?
    Wenn ich bool pruef (Saeugetier *s[]) eingebe, dann kommt die Fehlermeldung "canot convert from int* to int**) (Das hat meine Vermutung erzeugt, dass hier das Array von sich aus standardmäßig als Zeiger dient und deshalb nicht extra als Zeiger deklariert werden muss?

    Viele Grüße

    Viele Grüße



  • Ein Array ist kein Zeiger. Allerdings wird der Array-Name in den meisten Situationen implizit in einen Zeiger auf das erste Array-Element umgewandelt.
    (und bei Funktionsparametern sind die Angaben int *a und int a[] tatsächlich äquivalent, allerdings nur in der äußersten Dimension)



  • Dankeschön!

    Was passiert denn eigentlich bei

    cout << "der Speicherbereich verweist auf" << (void*) s
    

    die folgende Zeile bewirkt das gleiche:

    cout << "der Speicherbereich verweist auf" << s
    

    Ich hab zwar was von void - Zeigern gelesen, aber noch nicht so recht verstanden.
    bedeutet (void*) s hier evtl. dass mit dem Objekt s selbst gearbeitet wird, also eine andere Schreibweise für "s"?

    Gruß



  • (void*)s ist ein Cast im C-Stil, also eine Typ-Umwandlung. Das heißt, daß du den struct-Zeiger explizit in einen void-Zeiger (=Zeiger auf unstrukturierten Speicher) umwandelst. Bei der Variante cout << s; hast du ebenfalls eine Typumwandlung, allerdings eine implizite.
    (bei der Struktur macht das keinen Unterschied, aber wenn du stattdessen ein char *s verwendest, unterscheiden sich die Ausgaben)



  • Hi @ all,

    ich habe den Thread durchgelesen und noch eine Frage zu dem ganzen Thema.

    Ich habe folgende Zeilen geschrieben, und bitte euch diese zu kontrollieren ob das alles stimmt (vor allem die Kommentare)

    #include <cstdlib>
    #include <iostream>
    
    using namespace std;
    
     void kopie (int z) {
          cout << "FUNKTION kopie(int z) " <<endl;
          //z hat eine eigene Adresse und ist nicht mit a verbunden
          cout << "Die Adresse von z:" << &z << endl;
          cout << "Der WErt von z: " << z << endl << endl<< endl << endl;
          //eine Zuweisung bringt hier nichts, a bleibt unverändert!
          z = 99;
          }
    
     //Übergabe als Referenz
     void referenz (int &x) {
          cout << "FUNKTION referenz (int &x) " << endl;
          //die Adresse von y entspricht der von a, da mit einem
          //Alias gearbeitet wird????
          cout << "Die Adresse von x: " << &x << "  entspricht der von a, da ein Alias von a" << endl;
          cout << "Der Wert von x:    " << x << endl << endl <<endl << endl;
          //Änderungen würden sich hier direkt auf a auswirken!
    
          }
    
     void pointer (int &y) {
          cout << "FUNKTION pointer (int &y)" << endl;
          //y hat eine eigene Adresse, da ein dereferenzierter Zeiger übergeben wurde
          cout << "Die Adresse von y (&y):" << &y <<endl;
          cout << "Der Wert von  y (y)  :" << y <<endl << endl<< endl << endl;
          //Änderungen würden sich hier direkt auf b auswirken!
    
          }
    
    int main(int argc, char *argv[])
    {
    
        int a = 5;
        int b = 8;
        int *c = &b;
    
        cout << "Die Adresse von a: " << &a << endl;
        cout << "Der Wert von a:    " << a <<endl << endl;
    
        //hier wird die Zahl a übergeben (kein Pointer oder Referenz)???
        referenz(a);
        //hier wird die Zahl a übergeben (kein Point oder Referenz)??
        kopie(a);
    
        cout << "Die Adresse von    b  (&b): " << &b << endl;
        cout << "Der Wert von       b   (b): " << b << endl;
        cout << "Die Adresse von    c  (&c): " << &c << endl;
        cout << "Der Wert von       c   (c): " << c << " (also die Adresse von b)" << endl;
        //der Zeiger *c wird nun dereferenziert
        cout << "Der Wert - verweis c  (*c): " << *c << " (also der Wert von b)" << endl << endl;
        pointer(*c);
    
        ///////////////////////////////////////////////////////////////////////////////////////////
        ///////////////////////////////////////////////////////////////////////////////////////////
        //NEUER Quellcodebereich///////////////////////////////////////////////////////////////////
    
        //Beispiel REFERENZEN
        int aa = 6;
        //Was weiße ich hier genau zu?? ??
        //das heißt ja ungegfähr "die Adresse von bb entsprich aa (aber "aa" ist ja der Wert, oder??
        int &bb = aa;
    
        //BEISPIEL ZEIGER
        int cc = 9;
        //Dem Zeiger *dd wird die Adresse von cc zugewiesen
        int *dd = &cc;
    
        int ee = 11;
    
        cout << "bb" << bb << endl;
        //die Referenz bb erhält den Wert von ee ...
        bb = ee; 
        //... da bb direkt auf aa verweist, nimmt aa den Wert von ee an.
        cout << "aa" << aa << endl << endl << endl;
    
        //*dd liefert den dereferenzierten Wert
        cout << "cc" << cc << endl;
        cout << "*dd" << *dd << endl;
    
        //NUN VERWEIST dd AUF DIE ADRESSE VON "ee" 
        dd = &ee;
        cout << "cc erneut" << cc <<endl;
        cout << "*dd erneut" << *dd << endl;
    
        system("PAUSE");
        return EXIT_SUCCESS;
    }
    

    was ich noch nicht so ganz verstehe:

    Was wird bei "void referenz (int &x)" bzw. "void pointer (int &x)" übergeben? Es handelt sich doch in beiden Fällen um Objekte bzw. int - Werte??

    Tschau



  • http://ideone.com/wRmYi
    Wird es dadurch etwas klarer?
    Übrigens schreibt man im Normalfall int& n, nicht int &n, selbiges mit Zeigern.



  • Mario2hoch6 schrieb:

    Was wird bei "void referenz (int &x)" bzw. "void pointer (int &x)" übergeben? Es handelt sich doch in beiden Fällen um Objekte bzw. int - Werte??

    Genau genommen übergibst du an beide Funktionen eine Referenz. Übergabe per Zeiger sieht ein wenig anders aus:

    void pointer (int *y) {
          cout << "FUNKTION pointer (int *y)" << endl;
          //y hat eine eigene Adresse, da ein Zeiger übergeben wurde
          cout << "Die Adresse von y (&y):" << &y <<endl;
          //y enthält die Adresse einer übergebenen Variablen
          cout << "Der Wert von  y (y)  :" << y <<endl<
          //y ist ein Pointer und zeigt auf eine Variable
          cout << "Der Wert hinter y (*y):" << *y << endl<< endl << endl;
          //Änderungen an *y würden sich hier direkt auf b auswirken!
    }
    
    //Aufruf per:
    int a;
    zeiger(&a);
    


  • Hi,

    warum übergibst du hier

    pointer(&b)
    

    (also die Adresse der Variabeln) ich hätte das so gemacht:

    int b = 8;
        int* c = &b;
        pointer(c);
    

    c enthält ja auch die Adresse der Variablen b. Allerdings warum hast du hier keinen Zeiger mit "int* c" angelegt?

    Viele Grüße



  • Tom83 schrieb:

    Hi,

    warum übergibst du hier

    pointer(&b)
    

    (also die Adresse der Variabeln) ich hätte das so gemacht:

    int b = 8;
        int* c = &b;
        pointer(c);
    

    c enthält ja auch die Adresse der Variablen b. Allerdings warum hast du hier keinen Zeiger mit "int* c" angelegt?

    Viele Grüße

    Weil es nicht notwendig ist. Der Parameter (d.h. die Adresse von b) wird sowieso in den Stack-Bereich der Funktion kopiert, da ist es nicht notwendig, noch eine eigene Variable dafür anzulegen.



  • Hi,

    wie schauts dann aus, wenn ich so ein Konstrukt habe:

    //call by VALUE     
      void test3 (int q) {
           q = 77777;
           cout << " BEI q steht folgendes " << q << endl;
           }
    
        int s =99;
        int *r = &s;
        test3(*r);
        cout << "Der Wert von *r :" << *r << endl;
        cout << "Der wert von s:  " << s << endl;
    

    Nennt man das dass call by Value, oder hat das einen anderen Namen, weil ich einen derefferenzierten Zeiger übergebe?

    Viele Grüße



  • Das ist call by value, weil die Funktion einen Wert übergeben bekommt. Woher dieser Wert stammt, ist für den Aufruftyp unerheblich.

    Rein technisch gesehen ist auch die Zeiger-Variante "call by value" (allerdings mit einem "int*" Wert), semantisch wurde sie in C verwendet, um "call by reference" Semantik nachzubilden.



  • Hi!

    Danke!

    Ich hab mich jetzt mal an das Thema Zeiger auf Zeiger rangewagt:

    int s =99;
        int *r = &s;
        int **zeigeraufzeiger;
        int ***zeigeraufzeigeraufzeiger;
    
        zeigeraufzeiger = &r;
        zeigeraufzeigeraufzeiger = &zeigeraufzeiger;
    
        cout << "Adresse von s (&s)                                " << &s <<endl;
        cout << "Wert des Zeigers r (r)                            " << r << endl;
        cout << "Adresse des Zeiger r (&r)                         " << &r << endl;
        cout << "Wert des zeigeraufzeiger (z...)                   " << zeigeraufzeiger << endl;
        cout << "Adresse des zeigersaufzeiger (&z...)              " << &zeigeraufzeiger << endl;
        cout << "Wert des zeigeraufzeigeraufzeiger (z...)          " << zeigeraufzeigeraufzeiger << endl;
        cout << "Adresse des zeigeraufzeigeraufzeiger (&z...)      " << &zeigeraufzeigeraufzeiger << endl <<endl << endl;
    
        cout << "Wert von s                                                            " << s << endl;
        cout << "Wert des Zeigers r                                  (*r)              " << *r << endl;
    
        cout << "zeigeraufzeiger (z...) " << zeigeraufzeiger << endl;
        cout << "Wert des Zeigers zeigeraufzeiger (*zei...) (wert von r)                " <<*zeigeraufzeiger << endl;
        cout << "Wert des Zeigers zeigeraufzeiger (**zei...) (wert von s)               " << **zeigeraufzeiger << endl <<endl;
    
        cout << "zeigeraufzeiger (z...) " << zeigeraufzeigeraufzeiger << endl;
        cout << "Wert Zeiger zeigeraufzeigeraufzeiger (*z...)(wert von zeigeraufzeiger) " << *zeigeraufzeigeraufzeiger << endl;
        cout << "Wert des Zeigers zeigeraufzeigeraufzeiger (**z...) (Wert von r)        " << **zeigeraufzeigeraufzeiger << endl;
        cout << "Wert des Zeigers zeigeraufzeigeraufzeiger (***z..) (Wert von s)        " << ***zeigeraufzeigeraufzeiger << endl;
    

    Stimmen meine Angaben so?

    Viele Grüße



  • Nicht ganz.
    Zeile 18: Ziel des Zeigers
    Zeile 22: Ziel des Zeigers
    Zeile 23: Ziel des Zieles des Zeigers

    Zeile 27: Ziel des Zeigers
    Zeile 28: Ziel des Zieles des Zeigers
    Zeile 29: Ziel des Zieles des Zieles des Zeigers


Anmelden zum Antworten