Hilfe bei Pointern und Dynamischen Speicher



  • 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.



  • Kleine Frage man schließt ja in einem char* die letzte Stelle mit einer Null ab.

    Wenn ich das hier mache :

    char* name = "Darmstadt";
    //char* ptmp = name;
    name[9] = 0 ;
    
    cout << name << endl;
    

    Warum stürzt da mein Programm ab ? Laut Debugger macht er alles richtig.
    Er erstellt ein Array und an der "9" Stelle gibt er mir eine \0 .

    Kann es seien das ich durch

    char* name = "Darmstadt";
    

    ein Array erzeuge von [i] Stellen und ich dem Array an der 9ten Stelle eine Null angebe und er versucht sie auszugeben und "0" ja kein erlaubter Zustand seien darf?

    Oder hat das was mit dem Speicher zu tuen? Weil bei meinem Dynamischen Speicher muss ich ja mit einer NULL \0 abschließen
    Mfg



  • Der Compiler gibt eine Warnung aus. Ein Stringliteral stellt einen const char* - eun Zeiger auf einen Speicherbereich, welcher nicht beschrieben werden darf.



  • Und noch eine letzte Frage 🙂
    Bin dann echt durch und ihr habt mir bisher sehr sehr gut weitergeholfen 1000000 facher Dank dafür... folgendes :

    char* m_name;
    	char* name = "Darmstadt";
    	//char* ptmp = name;
    	m_name = new char[9];
    	m_name = name;
    

    Hab das mal zu Übungszwecken eingetippt und durch den Debugger gejagt zur Verdeutlichung... Kann mir mal einer erklären, warum bei

    m_name = name;
    

    ( das der Inhalt übernommen wird ist klar ) aber das die Adressen mit übernommen werden ist mir ein Rätsel ... Sind doch beide verschiedene Arrays?
    ist das Normal ?
    Weil in dem Script meines Profs wird das per For-Schleife realiesert und sozusagen Jeder einzelne Buchstabe ....

    for (m_curlenName=0;m_curlenName<m_maxlenName;m_curlenName++)
    	{
    		m_name[m_curlenName]=name[m_curlenName];
    	}
    


  • buu2188 schrieb:

    ( das der Inhalt übernommen wird ist klar )

    Ne, das ist nicht klar. Was heißt "übernehmen" für dich in diesem Fall? Das was Du wahrscheinlich als "Inhalt" verstehst ( "Darmstadt" ?) wird hier nicht kopiert.

    buu2188 schrieb:

    [...] aber das die Adressen mit übernommen werden ist mir ein Rätsel ... Sind doch beide verschiedene Arrays?

    Ein Array ist kein Pointer. Ein Pointer ist kein Array. Ein Array ist kein Pointer. Ein Pointer ist kein Array. Ein Array ist kein Pointer. Ein Pointer ist kein Array. Ein Array ist kein Pointer. Ein Pointer ist kein Array. Ein Array ist kein Pointer. Ein Pointer ist kein Array. Ein Array ist kein Pointer. Ein Pointer ist kein Array. Ein Array ist kein Pointer. Ein Pointer ist kein Array. Ein Array ist kein Pointer. Ein Pointer ist kein Array. Ein Array ist kein Pointer. Ein Pointer ist kein Array. Ein Array ist kein Pointer. Ein Pointer ist kein Array. Ein Array ist kein Pointer. Ein Pointer ist kein Array. Ein Array ist kein

    buu2188 schrieb:

    ist das Normal?

    Ja.

    Weder name noch m_name in deinem Beispiel ist ein Array. Ein Array ist ein Speicherblock, dessen Größe zur Übersetzung des Programms bereits feststeht (und auch nachträglich nicht geändert werden kann). Arrays leben auf dem Stapelspeicher (Stack), Dynamisch reservierter Speicher jedoch auf dem Freispeicher (Heap).

    char* m_name;              // Typ: char * (pointer to char)
    char* name = "Darmstadt";  // Typ: char * (pointer to char) 1)
    char foo[10];              // Typ: char[10] (array of 10 char)
    char bar[] = "Darmstadt";  // Typ: char[10] (array of 10 char)
    
    1. Eigentlich sollte name vom Typ char const * (pointer to const char) sein, da er auf ein Zeichenkettenliteral zeigt. Zeichenkettenliterale dürfen zur Laufzeit nicht beschrieben werden und sind deshalb const .

    Machst du nun foo = bar dann wird dir dein Lieblingscompiler sagen, daß du das nicht tun kannst. Arrays haben keine Kopiersemantik. Deshalb gibt es std::copy und Konsorten. Zu Fuß gehts eben mit einer Schleife.

    Machst du m_name = name so wird der Wert der Variable name der Variable m_name Zugewiesen. Dieser Wert ist eine Adresse - was auch sonst, beides sind schließlich Pointer. Beide Zeigen nach der Zuweisung auf den Anfang desselben Speicherbereichs. Der Speicherbereich, den du mit new char[9] (zu klein für "Darmstadt" !!) reserviert hast, ist dir nach der Zuweisung m_name = name nicht mehr Zugänglich, da du nirgends mehr die Adresse auf seinen Anfang gespeichert hast. Du kannst ihn weder verwenden noch jemals wieder ordentlich freigeben. Du hast ein Speicherleck.

    Das willst du aber wahrscheinlich nicht:

    #include <cstring>
    #include <iostream>
    
    class foo_t {
        private:
            char const * m_name;
    
        public:
            foo_t( char const * name )
            {
                m_name = name;  // dont. do. this.
            }
    
            void print_name() const
            {
                std::cout << m_name << '\n';  // booom!??
            }
    };
    
    int main()
    {
        char * bar = new char[ 10 ];
        std::strcpy( bar, "Darmstadt" );
    
        foo_t foo{ bar };
        foo.print_name();    // ok.
    
        delete[] bar;
    
        foo.print_name();  // BOOOOOOM!!
    }
    

    Da der Speicherbereich auf den bar zeigt vor dem zweiten Aufruf von print_name() freigegeben wurde, greift die Methode dann auf Speicher zu, der deinem Programm nicht mehr gehört. Das ist ein Fehler und fliegt dir früher oder später um die Ohren. Richtig wäre im Konstruktor einen ausreichend großen Speicherbereich anzufordern ( new[] ) und die Zeichenkette, auf die der Parameter name zeigt dahin zu kopieren. Ob nun mit einer Schleife, mit std::strcpy() oder std::copy() läuft aufs selbe raus.



  • was ist ein

    char*
    

    dann? Ich dachte es wäre das selbe wie

    char[]
    

    Ein Pointer auf das erste Element eines char?

    Bitte mal mit einem c++ Anfängerbeispiel sowie der Herr auf der ersten Seite des Threads 😞

    Vielen Dank 🕶



  • char* ist ein Pointer und char[] das Array. Das Array ist jedoch implizit in einen Pointer konvertierbar.

    char a[] = "hello";
    char* p = a;
    

Anmelden zum Antworten