Wie versteht man Zeigerarithmetik??



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



  • out schrieb:

    out schrieb:

    Nein, jetzt hast du einen Pointer auf ein char.

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

    Es geht ja so schnell hier, da überliest man schonmal was. :p



  • Dann halt hier mit Begründungen:

    #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 initialisieren, damit ich 5 Elemente habe
        int *pZahl = &Zahl[5]; //Pointer auf das Array initialisieren, damit ich auf die Adressen des Arrays zugreifen kann
        int a; // Variable deklarieren, damit ich fuer cin nachher Werte eingeben kann und diesmal nicht i habe
    
        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, damit ich z. B. 1,2,3,4,5 eigeben kann
        }
    
        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, also fuer insgesamt 5 Elemente( Element 0, Element 1, Element 2, Element 3, Element 4 sind nun mal 5 Elemente oder rechne ich falsch??????????????)
        }
    
        return 0;
    }
    

    [quote="cooky451"]

    silent_max schrieb:

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

    Und da Du den Code schon länger als sinnlos erachtest, bitte ich Dich darum, einen äquivalenten Code zu schreiben, der die Speicheradressen von insgesamt
    5 Elementen ausliest....


  • Mod

    silent_max schrieb:

    Und da Du den Code schon länger als sinnlos erachtest, bitte ich Dich darum, einen äquivalenten Code zu schreiben, der die Speicheradressen von insgesamt
    5 Elementen ausliest....

    Was ist der Sinn von folgende Zeilen: 10, 11, 15-19, 28? Was passiert, wenn du sie weglässt? Was hat die Ausgabe in Zeile 6 mit dem zu tun, was das Programm tatsächlich macht?



  • SeppJ schrieb:

    Was ist der Sinn von folgende Zeilen: 10, 11, 15-19, 28? Was passiert, wenn du sie weglässt? Was hat die Ausgabe in Zeile 6 mit dem zu tun, was das Programm tatsächlich macht?

    Ich wollte halt von 5 Elementen, die ich von der Tastatur einlese, die Adresse auslesen lassen.

    Dass man Zeile 10 prinzipiell weglassen kann, habe ich erst im Laufe des Threads mitbekommen.

    Edit:

    Was ich dazu sagen sollte:

    Ich wollte einfach ein Programm schreiben, das mir von 5 Elementen die ich per Tastatur einlese, um am Beispiel meines Programms zu bleiben von int, in 4 Byte Abständen die Speicheradressen auslesen lassen. Nicht mehr und auch nicht weniger



  • Also ich zum Beispiel, ich bin zu blöd zum Tapezieren und Anstreichen, ich kann nicht mal vernünftig einen Nagel in die Wand kloppen ...
    Ich hab das irgendwann eingesehen, und dann hab ich es einfach sein lassen ...


  • Mod

    silent_max schrieb:

    Ich wollte einfach ein Programm schreiben, das mir von 5 Elementen die ich per Tastatur einlese, um am Beispiel meines Programms zu bleiben von int, in 4 Byte Abständen die Speicheradressen auslesen lassen. Nicht mehr und auch nicht weniger

    Tja, tut es aber nicht.

    Meinst du nicht vielleicht, dass ich dich mit meiner Frage auf irgendetwas aufmerksam machen wollte oder bist du der Ansicht, dass dein Programm so absolut in Ordnung ist?



  • silent_max schrieb:

    Ich wollte einfach ein Programm schreiben, das mir von 5 Elementen die ich per Tastatur einlese

    Lass Dir Deine Zahlen mal zum Spaß ausgeben. Du füllst das Array nicht mit Werten, es ist totaler Blödsinn den Du da gemacht hast. Die Eingaben werden in a gemacht, und landen nie im Array.

    Blurry333 postet auch wieder. Ihr würdet euch bestimmt gut verstehen.


Anmelden zum Antworten