Inkrement Operatoren auf Zeiger



  • Hi@all

    Die Suche hat leider genauso wenig ausgespuckt wie google.
    Ich sitze hier jedenfalls gerade daran C++ zu lernen. Tja und nun bin ich bei den Pointern gelandet.

    Dabei ist mir noch etwas nicht ganz klar.

    #include <stdlib.h>
    #include <iostream>
    
    using namespace std;
    /*
     * 
     */
    int main(int argc, char** argv) 
    {
        int i = 1;
        int* iptr = 0;
    
        iptr = &i;
    
        while(i < 20)
        {
            cout << i << ": " << *iptr << "\n";
            *iptr++;//<-----betreffende Stelle
        }
    
        cout << endl;
    
        return (EXIT_SUCCESS);
    }
    

    Der Ablauf des Programms sieht hier so aus, dass die Schleife nicht abbricht, da i kein einziges mal inkrementiert wird.
    Wenn man an der Stelle "*iptr += 1;" oder "++*iptr" schreibt, dann terminiert die Schleife ganz normal.
    Bei "*iptr++" wird doch der Inhalt von der Variablen "i" genauso dereferenziert wie bei den anderen beiden Möglichkeiten. Allerdings tauchen dann große Zahlen auf und der Pointer "*iptr" scheint nicht mehr auf "i" zu zeigen.

    Ich hab mir das versucht so zu erklähren:

    ++*iptr;
    

    Zunächst wird hier der Wert von "i" dereferenziert, dann um 1 inkrementiert und der Wert dann an die Adresse im Pointer geschrieben. Also wird hier wirklich "i" inkrementiert.
    Ich komme auf die Annahme, da die Rangfolge der Operatoren "++" und dem (unäre) *-Operator die gleiche Priorität besitzen. Diese werden allerdings von rechts nach links ausgewertet.

    *iptr += 1;
    

    Analog der obigen Erklärung. Nur hat hier "+=" eine viel geringere Priorität als der (unäre) *-Operator.

    *iptr++;
    

    Hier wird dann der Pointer selbst inkrementiert, bevor dereferenziert wird.

    Bzw. heißt das dann das dieser um eine Stelle im Speicher weiter springt?
    Also um 4 Bytes, weil der Pointer selbst 4 Bytes groß ist oder um die Länge des Typs, auf die der Pointer zeigt?
    Wenn er dann "weiter gesprungen" ist, gibt er dann irgendwas aus, was da so im Speicher steht. Daher dann auch teilweise die verschiedenen Zahle in der Ausgabe?
    Bsp.:
    Ausgabe des obigen Programms:
    1: 1
    1: 2674024
    1: 1627418227
    1: 1
    1: 1629653476
    1: 16646392
    1: 1627408830
    1: 0
    1: 0

    [...]

    Hoffe mal es ist verständlich was ich meine. 😉

    Vielleicht könnt ihr mir ja dabei helfen, ob meine Annahmen richtig sind, oder aber wenn nicht mich dann ggf. korrigieren. 🙂

    Gruß

    Nighthawk2k10



  • Ich kommentiere mal deinen Code:

    #include <stdlib.h> //Gibt es in C++ nicht, sondern cstdlib
    #include <iostream> //OK
    
    using namespace std; //Naja, Geschmackssache
    
    int main(int argc, char** argv) //OK
    { 
        int i = 1; //OK
        int* iptr = 0; //OK
    
        iptr = &i; //OK
    
        while(i < 20) //OK (hier war ein Kommentar aufgrund eines Lesefehlers meinerseits)
        { 
            cout << i << ": " << *iptr << "\n"; //OK
            *iptr++; //Pointer erhöhen und unnötig dereferenzieren
        } 
    
        cout << endl; //OK
    
        return (EXIT_SUCCESS); //OK
    }
    

    Der Code erzeugt undefiniertes Verhalten. Dir gehört ja der Speicher der nach i nicht, oder?



  • Ja, das postfix-Inkrement hat eine höhere Priorität als die Dereferenzierung. Deshalb wird bei deinem Aufruf *iptr++; der Zeiger verschoben (und die Dereferenzierung ist nutzlos) und wandert geradeaus durch den Speicher - der Rest ist undefiniertes Verhalten.

    Wenn du etwas anderes erreichen willst, mußt du Klammern setzen: (*iptr)++; .



  • @CStoll
    Danke, dann war meine Annahme ja nicht ganz richtig.

    @EOutOfResources
    Ich weiß zwar nicht was "//WTF? Wenn i dort im RAM liegt dann," mir sagen soll, denn ich nahm an, dass es ersichtlich ist das es nur ein Test ist. Aber danke nochmal für das kommentieren, denn ich hatte oben nicht auf das mit C Library geachtet und das es ja auch das äquivalent in C++ gibt. 🙂

    Um wieviel Schritte läuft denn der Pointer dann durch den Speicher? Um seine eigene Speichergröße oder der des Typs oder sequentiell um 1?



  • Nighthawk2k10 schrieb:

    Um wieviel Schritte läuft denn der Pointer dann durch den Speicher? Um seine eigene Speichergröße oder der des Typs oder sequentiell um 1?

    Der Pointer läuft um die Größe des dahinterliegenden Typs im Speicher weiter.



  • Ja, das postfix-Inkrement hat eine höhere Priorität als die Dereferenzierung. Deshalb wird bei deinem Aufruf *iptr++; der Zeiger verschoben (und die Dereferenzierung ist nutzlos) und wandert geradeaus durch den Speicher - der Rest ist undefiniertes Verhalten.
    
    Wenn du etwas anderes erreichen willst, mußt du Klammern setzen: (*iptr)++;.
    

    Ist es die Priorität? Ich dachte dass es schon dadurch begründet wird, dass man von Rechts nach Links liest?



  • Ethon schrieb:

    Ich dachte dass es schon dadurch begründet wird, dass man von Rechts nach Links liest?

    In diesem Fall stimmt auch das Rechts-Nach-Links aber nicht immer:

    int a;
    struct
    {
      int a;
    } b;
    b.a++;
    


  • Nighthawk2k10 schrieb:

    Ich weiß zwar nicht was "//WTF? Wenn i dort im RAM liegt dann," mir sagen soll

    Ups, sorry! Ich habe den Code nicht sehr gründlich gelesen.


Anmelden zum Antworten