Hilfe bei Pointern und Dynamischen Speicher



  • Noch eine kleine Frage rein aus Interesse.
    Habe mal versucht ein Beispiel meines Prof's umzuschreiben und habe dabei folgendes Problem:

    Beispiel des Prof's:

    int N;
        double* x;
        cout << "Anzahl zu speichernder Werte: " << endl;
        cin >> N;
        x=new double[N];
    for (int i = 0 ; i < N ; i++)
        x[i]=0;
    
    delete[]x ;
    

    Ich habe mal das hier zusammen geschnipselt :

    int N;
    	char* x = "ABC";
    	cout << "Anzahl der Buchstaben anzeigen lassen?: " << endl;
    	cin >> N;
    	x = new char[N];
    
    	for (int i = 0 ; i < N ; i++)
    		x[i]=0;
    
    	cout << *x << endl;
    

    Bekomme das aber nur eine Adresse heraus 😕 Warum?

    Habe mir das Programm mal zusammen gebastelt damit ich mir das vorher genannte Thema mal an einem selbst gemachten Beispiel einfacher erkenntlich zu gestalten.

    Versteht ihr meine Problematik? Würde gerne eine Schleife realisieren mit einem char der einen Namen etc gespeichert hat den ich per schleife auf die Console herausgebe.

    Und nun noch eine ganz andere Frage:

    int x = 5;
    int *pTr;
    pTr = &x;
    

    pTr = Nur für Adressen?
    *pTr = Nur für Werte?

    MFG



  • buu2188 schrieb:

    Also sind character Pointer Zeiger auf die jeweiligen Blöcke eines Arrays?

    im prinzip schon.
    du schreibst also z.b. "char *a = new char[25];" und dann kannst du mit *a das erste element abrufen, mit *(a+1) das zweite, *(a+2) das dritte usw.

    was dein anderes problem angeht:
    1. wirfst du dein array weg.
    2. überschreibst du in dem programm dein array mit 0.
    3. lautet die abbruchbedingung idr. *a==0.

    &pTr: adresse der zeigervariablen
    pTr: in der zeigervariablen gespeicherte adresse
    *pTr: an in der zeigervariablen gespeicherten adresse gespeicherter wert



  • buu2188 schrieb:

    Also sind character Pointer Zeiger auf die jeweiligen Blöcke eines Arrays?

    Jein; sie zeigen, genau genommen, auf ein einzelnes Objekt vom Typ "char". Wie viele danach noch kommen mögen, ist in einem char* nicht enthalten.

    buu2188 schrieb:

    Deshalb muss ich einen neuen Character definieren und um +1 erhöhen für den zweiten Buchstaben des Arrys? 🙂

    Nein, es gibt verschiedene Möglichkeiten um auf nachfolgende chars zuzugreifen. Das wurde hier schon erklärt.



  • buu2188 schrieb:

    Habe mal versucht ein Beispiel meines Prof's umzuschreiben

    Als Lehrbeispiel ist das vielleicht geeignet, um Umgang mit Pointern zu lernen, aber in der Praxis wirst du diesen Code eher selten bis hoffentlich gar nicht sehen. Grund: keine Fehlerbehandlung, was passiert bei negativen Eingaben und außerdem wäre hier in C++ wohl ein std::vector<double> das Mittel der Wahl.

    buu2188 schrieb:

    Ich habe mal das hier zusammen geschnipselt :

    int N;
    	char* x = "ABC";
    

    Das ist schon falsch, dir fehlt const: du solltest eine Ausgabe wie "ISO C++11 does not allow conversion from string literal to 'char *'" bekommen. Wenn nicht, dann stell die Warnungen/Fehler richtig ein. Dann funktioniert natürlich auch die folgende Zuweisung auf x[i] nicht mehr. Nimm doch eine neue Variable!

    buu2188 schrieb:

    for (int i = 0 ; i < N ; i++)
    		x[i]=0;
    
    	cout << *x << endl;
    

    Bekomme das aber nur eine Adresse heraus 😕 Warum?

    Das wäre merkwürdig. Da sollte keine Adresse rauskommen, sondern nur das Zeichen mit dem Wert 0, das du vermutlich nicht am Bildschirm siehst, sowie der Zeilenumbruch.

    Ich glaube, du solltest dich dringend mit ein paar Kommilitonen zusammensetzen und die Grundlagen (was ist ein Zeiger etc.) noch einmal angucken. Das geht vermutlich besser/schneller als hier. Das soll dich aber nicht davon abhalten, hier gern konkrete Dinge nachzufragen.



  • Ein Pointer ist eine Variable, die eine Adresse speichert.

    Um an den Wert zu kommen, der an dieser Adresse liegt, muss man den Pointer dereferenzieren. Dafür ist der * Operator oder auch die [] da.

    Eine Besonderheit bei Pointern ist, das bei Addition mit einem integralen Typ die Größe des Elements (auf das der Zeiger verweist) berücksichtigt wird.

    x[i] ist identisch mit *(x+i)

    Der Pointer enthält keine weitere Information darüber, wie groß der Speicherbereich ist, auf den er zeigt.

    cout gibt bei einem Pointer dessen Inhalt (Adresse) aus, es sei denn, es ist ein char-Pointer.
    Bei char* wird das wie ein C-String behandelt.

    Das *x ist bei dir aber vom Typ char und ist bei dir 0.

    char* x = "ABC";  // 4 Zeichen 'A', 'B', 'C', 0
    
        for (int i = 0 ; x[i] != 0 ; i++)  // als Array
          cout << x[i] << endl;            
    
        for (char *p = x; *p; p++)         // mit Pointer  *p steht für *p != '\0'
          cout << *p << endl;
    

    Der Zeiger p wird hier gebraucht, da x ja weiterhin auf den Anfang der Zeichenfolge zeigen soll.



  • Vielen vielen Dank für eure Hilfe 🙂



  • DirkB schrieb:

    x[i] ist identisch mit *(x+i)

    Rätselfrage: ist x oder i der Pointer?



  • Andromeda schrieb:

    DirkB schrieb:

    x[i] ist identisch mit *(x+i)

    Rätselfrage: ist x oder i der Pointer?

    Ja



  • Andromeda schrieb:

    Rätselfrage: ist x oder i der Pointer?

    i zeigt halt auf was anderes 🙄



  • HansKlaus schrieb:

    Andromeda schrieb:

    Rätselfrage: ist x oder i der Pointer?

    i zeigt halt auf was anderes 🙄

    Auf was denn?



  • Andromeda schrieb:

    DirkB schrieb:

    x[i] ist identisch mit *(x+i)

    Rätselfrage: ist x oder i der Pointer?

    Solange da ein Pointer und ein integraler Typ ist, ist es egal.
    Dies ergibt sich aus dem Kommutativgesetz, dass für die Addition gültig ist.



  • Andromeda schrieb:

    HansKlaus schrieb:

    Andromeda schrieb:

    Rätselfrage: ist x oder i der Pointer?

    i zeigt halt auf was anderes 🙄

    Auf was denn?

    kommt halt darauf an, welchen wert i hat.



  • der witz ist, dass [] für eingebaute typen auch kommutativ ist.

    void foo (int* array, int i){
       assert(array[i] == i[array]);
    }
    


  • dove schrieb:

    der witz ist, dass [] für eingebaute typen auch kommutativ ist.

    Das ist kein Witz, sondern die logisch Folgerung daraus.



  • naja ob ich den wert von i als basisadresse nehme und dann den wert von array hinzuaddiere, oder umgekehrt ist ja auch egal.



  • DirkB schrieb:

    Andromeda schrieb:

    DirkB schrieb:

    x[i] ist identisch mit *(x+i)

    Rätselfrage: ist x oder i der Pointer?

    Solange da ein Pointer und ein integraler Typ ist, ist es egal.

    So ist es. 🙂

    DirkB schrieb:

    Dies ergibt sich aus dem Kommutativgesetz, dass für die Addition gültig ist.

    Das ergibt sich eher aus der C-Syntax, die sowas erlaubt.



  • DirkB schrieb:

    dove schrieb:

    der witz ist, dass [] für eingebaute typen auch kommutativ ist.

    Das ist kein Witz, sondern die logisch Folgerung daraus.

    logisch ist das nicht, nur wenn man wirklich die definition x[y] == *(x+y) ernst nimmt. die ist aber auch nicht absolut/in stein gemeißelt...

    struct Foo {
        int i;
        int const& operator*() const { return i; }
    
    };
    
    Foo operator+(Foo a, int i) {
     return a;
    }
    
    Foo operator+(int i, Foo a) {
     return a;
    }
    
    int main()
    {
        Foo f { 42 };
    
        *f; //ok
        *(f+0); //ok
        *(0+f); //ok
        f[0]; //ooops
    }
    


  • dove schrieb:

    DirkB schrieb:

    dove schrieb:

    der witz ist, dass [] für eingebaute typen auch kommutativ ist.

    Das ist kein Witz, sondern die logisch Folgerung daraus.

    logisch ist das nicht, nur wenn man wirklich die definition x[y] == *(x+y) ernst nimmt. die ist aber auch nicht absolut/in stein gemeißelt...

    struct Foo {
        int i;
        int const& operator*() const { return i; }
       
    };
    
     
    Foo operator+(Foo a, int i) {
     return a;
    }
        
    Foo operator+(int i, Foo a) {
     return a;
    }
    
    int main()
    {
        Foo f { 42 };
        
        *f; //ok
        *(f+0); //ok
        *(0+f); //ok
        f[0]; //ooops
    }
    

    Wenn man einfach Operatoren umbiegt, kann man natürlich jede Seltsamkeit hinfrickeln. Daher bevorzuge ich C. Bei einem C++-Codeschnipsel weißt du nie, was wirklich passiert.



  • wenn man den []-operator auch noch überlädt, klappts auch.



  • Andromeda schrieb:

    Wenn man einfach Operatoren umbiegt, kann man natürlich jede Seltsamkeit hinfrickeln. Daher bevorzuge ich C. Bei einem C++-Codeschnipsel weißt du nie, was wirklich passiert.

    ja, das überladen von operatoren ist eines der wesentlichen merkmale von C++. wenn man sich an bestehende konventionen hält, ist das auch überhaupt nicht schlimm. blöd ist es nur, wenn man einen operator falsch implementiert und daher mehr arbeit ausführen lässt, als nötig wäre. in C muss man sich dann eben darauf verlassen, das irgendwelche funktionen, die man aufruft, richtig und gut geschrieben sind.

    leider? reicht es eben nicht, operator+ und den dereferenzierungsoperator zu überladen, um dieselbe funktionalittät wie mit zeiger+integral zu bekommen. das ist aber so eine unbedeutende randerscheinung, dass man als normaler C++-anwender damit trotzdem gut leben kann.


Anmelden zum Antworten