Wie versteht man Zeigerarithmetik??



  • silent_max schrieb:

    #include<iostream>
    using namespace std;
     
    int main()
    {
        cout << "\t 5 Adressen um jeweils 4 Byte hochzaehlen lassen.\n";
        cout << "\n";
     
        int Zahl[5]; //Array mit 5 Elementen DEFINIEREN, NICHT INITIALISIEREN
        int *pZahl = &Zahl[5]; //Pointer auf das Array initialisieren DER POINTER ZEIGT HINTER DAS ARRAY UND WIRD NIE GEBRAUCHT
        int a; // Variable deklarieren UND DEFINIEREN, WIRD ABER NIE WIRKLICH GEBRAUCHT
     
        cout << "Geben Sie fuenf Zahlen ein.\n";
     
        for(int i=0; i<5; i++)
        {
            cout << "Zahl[" << i <<"]: "; //Für Elemente von 0 bis 4 Werte bzw. Zahlen eingeben
            cin  >> a; //Variable a fuer die Werteeingabe A WIRD NICHT WEITER VERARBEITET, WOZU ALSO?
        }
     
        cout << "Die Adresse der jeweiligen Zahl lautet wie folgt:\n";
     
        for(int i=0; i<5; i++)
        {
            cout << "Zahl[" << i << "]: " << &Zahl[i] << "\n"; // Adresse fuer die Elemente 0 bis 4 ausgeben
        }
     
        return 0;
    }
    

    Ich hoffe, dass es jetzt bisschen verständlicher wird??



  • Namal schrieb:

    Belli schrieb:

    Nein, sie könnten auch mit 17 anfangen. Tun sie aber einfach nicht.

    Ja entschuldige wenn ich es missverständlich ausgedrücklt habe: Wieso werden in einem Vektor/Array bei C/C++ die Element von 0 bis n-1 nummeriert und nicht von 1 bis n?

    Keine Ahnung, aber warum nicht von 17 bis 17 + n - 1?
    Vielleicht gewachsen aus der Maschinensprache ... weil man dort soviel ich weiß, mit Offsets rechnet/gerechnet hat.
    Letztendlich ist es aber doch egal.



  • Belli schrieb:

    silent_max schrieb:

    [cpp]

    [...]

    int *pZahl = &Zahl[5]; //Pointer auf das Array initialisieren DER POINTER ZEIGT HINTER DAS ARRAY UND WIRD NIE GEBRAUCHT

    [...]

    Ich hoffe, dass es jetzt bisschen verständlicher wird??

    Ein Pointer AUF das Array wäre übrigens:

    int *pZahl = Zahl;
    

    oder von mir aus auch:

    int *pZahl = &Zahl[0];
    


  • Namal schrieb:

    qweasdyxc schrieb:

    Du darfst aber nicht auf Zahl[5] zugreifen wenn dein verdammtes Array nur 5 Elemente hat. Himmel!

    So offtopmäßig: Warum müssen die Zählindizes mit 0 anfangen? Ich meine hat es einen bestimmten Grund oder eine Notwendigkeit?

    Informatiker mögen halt die 0. :p Wenn etwas nicht bei 0 beginnt, bin ich verwirrt. Außerdem bezeichnet der Index ja den Offset. Wenn es kein Offset gibt (0), landest du am Anfang. Darum finde ich es auch logisch, dass es bei 0 beginnt. Im Übrigen kannst du auch den Variablennamen als Offset hernehmen, also kannst statt Zahl[0] auch 0[Zahl] schreiben.



  • Namal schrieb:

    Wieso werden in einem Vektor/Array bei C/C++ die Element von 0 bis n-1 nummeriert und nicht von 1 bis n?

    Es ist einfach konsequenter von 0 zu starten. Ausserdem macht es einige Rechnungen kürzer.

    vec[i % vec.size()] vs. vec[i % vec.size() + 1]
    vec[i/2] vs vec[(i-1)%2+1]
    

    Why numbering should start at zero
    Wikipedia: Zero-based numbering



  • Belli schrieb:

    Keine Ahnung, aber warum nicht von 17 bis 17 + n - 1?

    Ja warum eigentlich nicht? Würde genausoviel Sinn machen wie jetzt.



  • out schrieb:

    Im Übrigen kannst du auch den Variablennamen als Offset hernehmen, also kannst statt Zahl[0] auch 0[Zahl] schreiben.

    Bei einem std::vector oder einem std::array geht das schon nicht mehr.



  • Namal schrieb:

    Belli schrieb:

    Keine Ahnung, aber warum nicht von 17 bis 17 + n - 1?

    Ja warum eigentlich nicht? Würde genausoviel Sinn machen wie jetzt.

    Weil die 0 eben vor der 1 kommt?
    Außerdem macht das wie gesagt wegen Offets Sinn.

    arr[0] ist äquivalent zu arr + 0
    arr[1] ist äquivalent zu arr + 1*sizeof(*arr)
    arr[2] ist äquivalent zu arr + 2*sizeof(*arr)

    etc



  • out schrieb:

    Informatiker mögen halt die 0. :p Wenn etwas nicht bei 0 beginnt, bin ich verwirrt.

    So einfach kann es nicht sein. Es gibt Programmiersprachen, bei denen der Index bei 1 beginnt.



  • Belli schrieb:

    Ein Pointer AUF das Array wäre übrigens:

    int *pZahl = Zahl;
    

    oder von mir aus auch:

    int *pZahl = &Zahl[0];
    

    Nein, jetzt hast du einen Pointer auf ein char. Wenn du ein Pointer auf das Array willst, musst du schon

    int (*pZahl)[5] = &Zahl;
    

    schreiben.



  • Belli schrieb:

    Nein, sie könnten auch mit 17 anfangen. Tun sie aber einfach nicht.

    Es gibt einen ganz eindeutigen Grund, wieso sie mit 0 Anfangen, und wieso es deutlich weniger Sinn hat dass das erste Element den Index 17 hat.

    Ein Array (ich spreche hier sowohl von echten Arrays als auch von sequentiellen STL-Containern) hält intern einen Zeiger auf das erste Element.

    int a[] = {1, 2, 3};
    

    Dank dem array to pointer decay kann a sogar implizit in einen Zeiger auf das erste Element konvertiert werden - weil a intern genau diesen Zeiger hält, redet man von decay - engl. für Zerfall; a kann also zu diesem Zeiger zerfallen.

    Natürlich hat a nicht den Typ int* !
    Sondern int[3] .

    und was macht jetzt der Index-Operator?
    Ganz einfach.

    a[x]
    

    Ist dasselbe (bzw. implementiert durch)

    *(a + x) // a zerfällt in der Summe in einen Zeiger. Dieser wird um x Elemente verschoben und dereferenziert.
    

    Man sieht sofort: Will man auf das erste Element zugreifen, dann muss man nur 0 angeben.
    Dann ergibt der Ausdruck

    *(a + 0)
    

    ➡

    *a
    

    Und weil (wie oben besprochen) a implizit in einen Zeiger auf das erste Element konvertiert werden kann, ist das Ergebnis dieses Ausdrucks eine Referenz auf das erste Element.

    Die obige Methode ist einfach und performant. Die zusätzliche 17 in der Summe wäre schlicht und einfach unnötig und könnte sich möglicherweise auch auf die Performance auswirken (da weiß ich leider nix näheres), was, selbst so klein die Auswirkung auch sein mag, bei sehr großen Arrays und vielen Iterationen durchaus eine maßgebende Bedeutung haben kann.


  • Mod

    dijkstra schrieb:

    Bei einem std::vector oder einem std::array geht das schon nicht mehr.

    Das sind ja auch nutzerdefinierte Datentypen (wobei der "Nutzer" der STL-Hersteller ist). Du kannst dir gerne einen eigenen Datentypen basteln, der ein Offset erlaubt.



  • Ethon schrieb:

    Namal schrieb:

    Belli schrieb:

    Keine Ahnung, aber warum nicht von 17 bis 17 + n - 1?

    Ja warum eigentlich nicht? Würde genausoviel Sinn machen wie jetzt.

    Weil die 0 eben vor der 1 kommt?
    Außerdem macht das wie gesagt wegen Offets Sinn.

    arr[0] ist äquivalent zu arr + 0
    arr[1] ist äquivalent zu arr + 1*sizeof(*arr)
    arr[2] ist äquivalent zu arr + 2*sizeof(*arr)

    etc

    Du hast *( ~ ) vergessen :xmas1:

    Verdammt, viel zu spät! 😡



  • out schrieb:

    Belli schrieb:

    Ein Pointer AUF das Array wäre übrigens:

    int *pZahl = Zahl;
    

    oder von mir aus auch:

    int *pZahl = &Zahl[0];
    

    Nein, jetzt hast du einen Pointer auf ein char. Wenn du ein Pointer auf das Array willst, musst du schon

    int (*pZahl)[5] = &Zahl;
    

    schreiben.

    Humbug!



  • Belli schrieb:

    Humbug!

    👍



  • out schrieb:

    Nein, jetzt hast du einen Pointer auf ein char.

    char, wie komm ich auf char 😕 ich meinte natürlich int.

    Sone schrieb:

    Ein Array (ich spreche hier sowohl von echten als auch von sequentiellen STL-Containern) ist intern einfach ein Zeiger auf das erste Element des Arrays im Speicher.

    Nimm den Satz aus deinem Post raus. 🤡



  • out schrieb:

    Sone schrieb:

    Ein Array (ich spreche hier sowohl von echten als auch von sequentiellen STL-Containern) ist intern einfach ein Zeiger auf das erste Element des Arrays im Speicher.

    Nimm den Satz aus deinem Post raus. 🤡

    Korrigiert, ich schäme mich. 😃
    War im Eifer des Gefechts :xmas1:



  • silent_max schrieb:

    Ich hoffe, dass es jetzt bisschen verständlicher wird??

    Du hast (wie erwartet) vergessen die Begründungen mit anzugeben. Hat vielleicht was damit zu tun, dass 90% des Codes sinnlos ist.



  • Belli schrieb:

    Humbug!

    Was ist da Humbug? Wenn du int* p schreibst hast du nunmal einen Zeiger auf ein int. War schon immer so.



  • Na und?
    Du hast behauptet, ich hätte einen Zeiger auf char.


Anmelden zum Antworten