Probleme mit Sichtbarkeit von Variable und Array



  • Hallo,
    ok dann warte ich auf deine Fortsetzung. Zwischen durch noch das (ich habe etwas Neues ausprobiert):

    int **zeiger;
     int zahl=4;
     *zeiger=&zahl;
     zeiger=&(*zeiger); //Warum geht das nicht
     ShowMessage(String(**zeiger));
    

    Wieder kommt ein Laufzeitfehler, doch dachte ich, dass ich hier nun auch Pointer1 und Pointer2 eine Adresse zugewiesen habe! Ich habe versucht auf die Variable "buf" zu versichten

    Vielen Dank für eure tolle Hilfe
    lg, freakC++



  • Hallo

    Bis zur dritten Zeile hast du nichts verändert, deshalb kommt der gleiche Fehler wie vorher. Vor dem Verwenden von *zeiger must du zeiger erstmal eine gülige Speicheradresse zuweisen! Und daran krankt auch das hier :

    zeiger=&(*zeiger);
    

    Denn bevor die linke Seite zugewiesen wird, wird die rechte Seite ausgewertet. Und dort verwendest du wieder *zeiger vor zeiger. Das kann so nicht klappen. Und ganz kann ich auch nicht verstehen was du damit bewirken willst. Versuchst du einen Zeiger auf sich selbst zeigen zu lassen? Ganz schlechte Idee, und auch gar nicht hilfreich bei einem Zweifach-Zeiger.

    bis bald
    akari



  • So, hier wie versprochen der Rest:

    freakC++ schrieb:

    arrListe[0]=new CRechteck (4,4);
    
    /*ich weise der ersten Instanz von CRechteck Speicherplatz zu und übergeben zwei Zahlen an den Konstruktor.*/
    

    Richtig. Und dieser zugewiesene Speicherplatz kann über das 1. Element des Array (vom Typ Zeiger auf CRechteck) angesprochen werden.

    Beispiel:

    int FlaecheninhaltB= (*arrListe[0]).Width * arrListe[0]->Height; // beide Zugriffe auf arrListe sind gleichwertig verwendbar
    

    freakC++ schrieb:

    Warum muss ich hier nie vor arrListe ein Sternchen schreiben. Es ist doch eigentlich das gleiche wie mit **zeiger und da musste ich in einem Schritt auch *zeiger schreiben.

    Felder und Zeiger sind miteinander verwandt, das spielt hierbei eine Rolle. Lies dazu bitte den Link unten.

    freakC++ schrieb:

    Vorallem der zweite Quelltext ist mir wichtig, da dieser mir momentan noch Kopfschmerzen bereitet. Warum steht das Sternchen genau vor [zahl].

    Zum 2. Quelltext nochmal (ich glaub du meinst eher den 3. aus deinem vorletzten post): Das Sternchen gehört nicht vor [zahl] sondern hinter CRechteck! CRechteck* ist die Typangabe für das Array, welches also dann vom Typ Zeiger auf CRechteck ist.

    Ich weiß auch nicht wie man es noch einfacher erklären soll. Deklarationen, Definitionen und Initialisierungen sind Grundlagen der Programmierung. Und wenn man mit Zeigern arbeiten möchte, sollte man die Grundlagen dazu zu 90% verinnerlicht haben. Dazu gehören Zeigerdeklaration, Zeigerdefinition und Zeigerdereferenzierung! Ich empfehle nochmal ein einfaches Tutorial zum Thema Zeiger (engl. Pointer) und eins zum Thema Felder (engl. Array)... 😉

    Hier mal was zum Lesen über Zeiger.

    MfG



  • Hallo zusammen,
    vielen Dank für eure Antworten. Ich komme dem vollen Verständnis immer näher, doch merke ich, dass mich immer noch ein paar Denkfehler plagen. Die Sache mit dem Rechteck habe ich verinnerlicht. Doch ein paar Fragen zum anderen Quelltext bleiben. Ich habe mal eine kleine Zeichnung gemacht, die euch zeigen soll, wie ich mir das alles vorstelle. Folgender Quelltext nochmal:

    int zahl=5;
    int **zeiger;
    int *buf;
    zeiger=&buf;
    *zeiger=&zahl;
    

    So stelle ich mir das vor.

    //Ich kann hier leider keine ASCII Zeichnungen machen. Daher hier der Link:

    http://i1.fastup.de/show.asp?file=zeiger(1).jpg
    (der Link ist die ganze Zeile und nicht nur das Unterstrichende)

    Mein Problem ist nun die Verbindung zwischen Zeiger1 und Zeiger 2. Zeiger1 muss auch auf Zeiger2 zeigen. Wenn ich folgendes schreibe:

    int **zeiger;

    zeigt, dann automatisch Zeiger ein auf Zeiger 2? Wenn ja, dann müsste doch auch Zeiger1 von Anfang an eine Speicheradresse haben, denn ein Zeiger ohne Speicheradresse kann doch auf nichts zeigen.

    2.)Warum muss buf ein pointer sein?? Zeiger1 braucht doch nur eine Adresse. Kann dies nicht auch eine Adresse von einer int Variablen sein?

    Ich habe schon einiges zu C++ durchgearbeitet, doch hatte ich noch kein Buch, das sich derart mit Zeigern auseinander setzt. Ich werde mir wohl bald
    ein anpruchvolleres kaufen. Da mich die ganze Materie total interessiert, hoffe ich zum einen auf eure Geduld und zum anderen, dass ich bald alles verstanden habe.

    Vielen, vielen Dank
    lg, freakC++



  • *grummel**

    freakC++ schrieb:

    Wenn ich folgendes schreibe:

    int **zeiger;
    

    zeigt, dann automatisch Zeiger1 auf Zeiger 2?

    NEIN! Da zeigt überhaupt noch garnix irgendwohin. Damit deklarierst du nur einen Zeiger, der auf einen anderen Zeiger zeigen KANN (vom Typ her)!
    Es ist kein Zeiger auf int, sondern ein Zeiger auf Zeiger auf int!
    Du hast einen Zettel auf dem steht eine Zahl (Zettel 0 = int-Variable). Dann schreibst du einen Zettel, darauf schreibst du wo der Zettel mit der Zahl liegt (Zettel 1 = Zeiger 1 oder buf). Dann schreibst du einen Zettel, auf dem steht wo der Zettel liegt auf dem steht wo der Zettel mit der Zahl liegt (Zettel 2 = Zeiger 2 oder pointer haben wir die hier glaube genannt). Wenn du jetzt vergisst auf den Zettel 1 etwas draufzuschreiben, findest du mit Zettel 2 nicht Zettel 0, weil du Zettel 2 liest, dann zu Zettel 1 gehst, da aber nichts draufsteht.

    MfG



  • Hallo Kolumbus,
    vielen Dank...auch wenn ich wahrscheinlich für euch total duzmm erscheine. Sorry, wenn ich dich erbost habe :p . Ich habe mir alles nochmal durchgelesen und denke, dass ich es nun (endlich) verstanden habe. Noch eine Frage 😃 :

    Warum muss buf selber ein Pointer sein? Wenn ich folgende schreibe, dann brauche ich sogar zwei Sterne:

    int ***zeiger;
    int **buf; //brauche nun zwei Sternchen
    int *kuf;
    zeiger=&buf; //zeiger braucht nur ne Adresse. Warum reicht nicht *buf
    *zeiger=&kuf;
    int zahl=5;
    **zeiger=&zahl;
    ShowMessage(String(***zeiger));
    

    Auch wenn das wahrscheinlich totaler Hirngespinst ist, habe ich nun allen Zeigern eine Adresse zugewiesen. Wenn ich dem ersten Zieger (zeiger) eine Adresse zuweisen möchte, brauche ich einen Zeiger mit zwei Sternchen.
    Warum? zeiger braucht doch "nur" eine Adresse. Warum nimmt er diese nicht von einem "normalen" Pointer?

    int zahl=5;
    int **zeiger;
    int *buf;
    zeiger=&buf; //Auch hier weise ich zeiger eine Adresse zu. Oben geht das 
    *zeiger=&zahl; //aber nicht
    

    Vielen Dank
    lg, freakC++



  • Hi,

    ich denke mal, du startest deine Anwedung im Debuggermodus und setzt einen Haltepunkt auf deinen allerersten Zeiger
    und setzt den Cursor darüber. In dem kleinen Hintfenster siehst du nun, wie die Variablen und Zeiger belegt sind.

    Mit einem Wert oder einer Speicheraddresse. Du kannst auch das Fenster "Liste überwachter Ausdrücke" öffnen und alles dort
    eintragen.

    Sehr interessant ! 😉

    mfg
    kpeter



  • freakC++ schrieb:

    Hallo Kolumbus,
    vielen Dank...auch wenn ich wahrscheinlich für euch total duzmm erscheine. Sorry, wenn ich dich erbost habe :p . Ich habe mir alles nochmal durchgelesen und denke, dass ich es nun (endlich) verstanden habe. Noch eine Frage 😃 :

    Warum muss buf selber ein Pointer sein?

    Damit die CRechteck-Geschichte funktioniert wie du es wünschst (wenn ich mich richtig erinnere).

    freakC++ schrieb:

    Wenn ich folgende schreibe, dann brauche ich sogar zwei Sterne:

    int ***zeiger;
    int **buf;                      // brauche nun zwei Sternchen
    int *kuf;
    zeiger= &buf;                   // zeiger braucht nur ne Adresse. Warum reicht nicht *buf
                                    // Antwort: weil eine Adresse in C++ nunmal mit & ermittelt wird
                                    // oder wie meinst du die Frage?
    *zeiger= &kuf;                  // ist gleichwertig der folgenden Zeile:
        buf= &kuf;
    int zahl= 5;
    **zeiger= &zahl;                // ist gleichwertig den folgenden 2 Zeilen:
        *buf= &zahl;
        kuf= &zahl;
    ShowMessage(String(***zeiger)); // ist gleichwertig den folgenden 3 Zeilen:
        ShowMessage(String(**buf));
        ShowMessage(String(*kuf));
        ShowMessage(String(zahl));
    

    Auch wenn das wahrscheinlich totaler Hirngespinst ist, habe ich nun allen Zeigern eine Adresse zugewiesen.

    Richtig, hier sind alle Zeiger korrekt initialisiert! Sieht ja schon ganz brauchbar aus.

    freakC++ schrieb:

    Wenn ich dem ersten Zieger (zeiger) eine Adresse zuweisen möchte, brauche ich einen Zeiger mit zwei Sternchen.
    Warum? zeiger braucht doch "nur" eine Adresse. Warum nimmt er diese nicht von einem "normalen" Pointer?

    int zahl= 5;
    int **zeiger;
    int *buf;
    zeiger= &buf;     // Auch hier weise ich zeiger eine Adresse zu. Oben geht das aber nicht
    *zeiger= &zahl;   // => das hier geht oben nicht? ist auch richtig, denn oben müsste es (wie dort bereits geschrieben) so aussehen:
        **zeiger= &zahl;
    

    Du hast das mit den Zeigertypen noch nicht verstanden. Ein Zeiger ist eine Variable. Eine Zeigervariable enthält jedoch keinen Wert im klassischen Sinne, sondern eine Speicheradresse. Damit dein Programm später noch weiß, wie es das, worauf du mit dem Zeiger zeigst, interpretieren soll hat der Zeiger einen Typ (genau wie eine Variable). Ein Zeiger kann zB. vom Typ "Zeiger auf int" sein - dann kann in dem Zeiger eine Adresse eines Integer gespeichert werden. Der Zeiger wird so deklariert:

    int* Zeiger;
    

    So solltest auch du Zeiger deklarieren, nicht so:

    int *Zeiger;
    

    . Dann geht dir vielleicht in Fleisch und Blut über, dass das Sternchen in der Deklaration zur TYPVEREINBARUNG gehört.
    Wenn du jetzt so einen int-Zeiger deklariert hast und stellst nun fest dass du aus irgendeinem Grund einen Zeiger auf diesen Zeiger brauchst, deklarierst du den Zeiger auf den int-Zeiger so:

    int** Zeiger2;
    

    Das mit dem dereferenzieren liest du dir am Besten selbst nochmal durch!

    Hinweis: Das Sternchen bei der Deklaration des Zeigers hat nichts mit dem Sternchen zu tun, welches du bei der Arbeit mit dem Zeiger verwendest! ⚠

    Alles was was hier versucht wird zu erklären zielt darauf ab dass du die Konstruktion / Vorschläge für das CRechteck-Projekt verstehst. Also frag' nicht wozu du Zeiger auf Zeiger brauchst - das zielt darauf ab deine Vorstellungen zu realisieren! 😉

    MfG



  • Hallo Kolumbus,
    viele Dank für deine Antwort.

    Antwort: weil eine Adresse in C++ nunmal mit & ermittelt wird
    oder wie meinst du die Frage?

    Ich meine das so (die Sache mit CRechteck ist übrigens abgeschlossen):

    int zahl=5;
    int ***zeiger; //ich muss allen Zeigern eine Adresse zuweisen.
    int *buf;
    int *kuf;
    
    zeiger=&buf; //Zeiger 1 bekommt seine Adresse
    *zeiger=&kuf;//Zeiger 2 bekommt seine Adresse
    **zeiger=&zahl;//nun ist das möglich und ich kann folgendes schreiben:
    
    ShowMessage(String(***zeiger));
    

    Dieser Quelltext ist falsch. Ich dachte jedoch, dass ich nun allen zeiger eine Adresse zugewiesen habe. Ich muss aber das schreiben:

    int zahl=5;
    int ***zeiger; //ich muss allen Zeigern eine Adresse zuweisen.
    int **buf; //Zwei Sternchen!!!!!!
    int *kuf;
    
    zeiger=&buf; //Zeiger 1 bekommt seine Adresse
    *zeiger=&kuf;//Zeiger 2 bekommt seine Adresse
    **zeiger=&zahl;//nun ist das möglich und ich kann folgendes schreiben:
    
    ShowMessage(String(***zeiger));
    

    Warum muss ich **buf schreiben. Ich wil doch "nur" zeiger und *zeiger eine Adresse zuweisen....so wie wir es schon vorher gemacht haben.

    Vielen Dank
    lg, freakC++

    PS.: Wenn ich diesen letzten Schritt verstandne habe, dann sage ich endlich zu diesem Thread: -close- 😃



  • Hallo

    Im Speicherlayout sind Zeiger und Zeiger auf Zeiger gleich. Aber der C++ Compiler prüft eben streng auf Typen, und da ist Zeiger und Zeiger auf zeiger nicht gleich. Deshalb must du immer das richtige Zeiger-Level verwenden. Denn buf selber ist ja erstmal unabhängig von zahl oder zeiger. Auch von buf aus soll ja der Wert in zahl erreicht werden, und dazu muß der Typ Zeiger auf Zeiger sein, nicht nur Zeiger.

    bis bald
    akari



  • Hallo akari,
    vielen Dank! Dann habe ich es verstanden.
    Ich habe durc diesen Thread sehr viel gelernt. Viele Dank dafür - ihr seit echt toll 🙂

    lg, freakC++

    -close-


Anmelden zum Antworten