Fragen zu Pointern ..



  • Ich habe irgendwie noch ein wenig Verständisprobleme beim Thema Pointer und wollte mir daher hier noch einmal ein wenig Rat holen.

    Erst einmal verstehe ich nicht ganz, wann man denn eigentlich konkret überhaupt Pointer braucht? Soweit ich weiß sind diese ja auf jeden Fall schon eimnal nützlich, wenn man etwas suchen will, bspw. in einem char * oder nicht?
    Ich habe auch oft gelesen, dass man Pointer nur dann verwenden sollte, wenn man wirklich muss aber wann muss man denn wirklich Pointer verwenden und wann nicht? Hat da vielleicht auch jemand bspw. in dem Kontext, die das veranschaulichen?

    Dann noch einmal zwei konkrete Fragen:
    1. Wenn ich eine Methode habe, die so aussieht:

    int strToUpper(char *str) {
        while(*str) {
            *str = toupper(*str);
            ++str;
        }
        return 0;
    }
    

    modifiziert diese dann den char *, den ich in die Methode reingebe oder nicht? Ich dachte eigentlich, das es in C so keine Call by Reference gibt?

    2. Ich habe gerade auch ein konkrete Problem und zwar habe ich einen Buffer (char 😉 in dem Informationen eingelesen werden und diesen übergebe ich dann an eine Methode, die die Informationen in der Datei oder in dem Buffer parsen soll:

    int parseFile(char *buffer) {
        if(!parse_information1(buffer))
            return 0;
        if(!parse_information2(buffer))
            return 0;
        if(!parse_information3(buffer))
            return 0;
    
        return 1;
    }
    

    Wie kann ich dann den Stand des Buffers aus der ersten Methode an den zweiten übergeben? Ich bewege mich in den Methoden nämlich mit

    buffer += ;
    

    in dem Buffer weiter aber wenn ich jetzt in der zweiten Methode bin, dann habe ich das Problem, dass der Buffer ja wieder am Anfang steht aber das will ich nicht.
    Kann ich das also so richten, das der Buffer bei der Übergabe an die zweite Methode auf dem Stand ist, auf dem er in der ersten am Ende war, ohne das ich den Buffer so als return Wert zurückgebe? Der return Wert der Methoden soll nämlich eigentlich ein int bleiben.



  • Liq schrieb:

    Ich dachte eigentlich, das es in C so keine Call by Reference gibt?

    Klar gibt es in C call by reference. Es gibt kaum etwas, das in C nicht geht.

    Ich bewege mich in den Methoden nämlich mit

    C:
    buffer += ;
    

    Da wird dir wohl nix Anderes übrig bleiben als dir die Position zu merken. Wobei mir der code-Auschnit nicht nach C aussieht. So geht man in C nicht mit arrays um.


  • Mod

    EOP schrieb:

    Liq schrieb:

    Ich dachte eigentlich, das es in C so keine Call by Reference gibt?

    Klar gibt es in C call by reference. Es gibt kaum etwas, das in C nicht geht.

    Irgendjemand wird garantiert gleich einwerfen, dass das Übergeben eines Pointers (by value) ganz was anderes wäre, als einen Parameter direkt by reference zu übergeben.



  • Liq schrieb:

    Ich habe auch oft gelesen, dass man Pointer nur dann verwenden sollte, wenn man wirklich muss aber wann muss man denn wirklich Pointer verwenden und wann nicht? Hat da vielleicht auch jemand bspw. in dem Kontext, die das veranschaulichen?

    Wenn er auf NULL zeigen können soll (Rückgabe von Suchergebnis, das evtl nicht da ist).
    Wenn er geändert werden können muss (doppelt verkettete Liste).

    Liq schrieb:

    2. Ich habe gerade auch ein konkrete Problem und zwar habe ich einen Buffer (char 😉 in dem Informationen eingelesen werden und diesen übergebe ich dann an eine Methode, die die Informationen in der Datei oder in dem Buffer parsen soll:

    int parseFile(char *buffer) {
        if(!parse_information1(buffer))
            return 0;
        if(!parse_information2(buffer))
            return 0;
        if(!parse_information3(buffer))
            return 0;
    
        return 1;
    }
    

    Wie kann ich dann den Stand des Buffers aus der ersten Methode an den zweiten übergeben? Ich bewege mich in den Methoden nämlich mit

    buffer += ;
    

    in dem Buffer weiter aber wenn ich jetzt in der zweiten Methode bin, dann habe ich das Problem, dass der Buffer ja wieder am Anfang steht aber das will ich nicht.
    Kann ich das also so richten, das der Buffer bei der Übergabe an die zweite Methode auf dem Stand ist, auf dem er in der ersten am Ende war, ohne das ich den Buffer so als return Wert zurückgebe? Der return Wert der Methoden soll nämlich eigentlich ein int bleiben.

    Brauchst nichtmal den int, wenn Du verabredest, daß nur jemand, der was erfolgreich geparst hat, dabei auch Ziechen weggelesen hat. Wolltest ja eh unbedingt Zeiger auf Zeiger üben. Und vielleicht brauchste die Rückgabe für den AST.

    void parseCommandDo(char **buffer) {
        //must read all three parts
        char* lb=*buffer;
        parseKeywordDo(&lb);
        if(lb==*buffer) return;//is a return false
        parseCommand(&lb);
        if(lb==*buffer) return;//is a return false
        parseWhile(&lb);
        if(lb==*buffer) return;//is a return false
        *buffer=lb;
    }//is a return true
    
    void parseCommand(char** buffer) {
        //must read one of the parts
        char* lb=*buffer;
        parseCommandDo(buffer);
        if(*buffer!=lb) return;//is a return true
        parseCommandIf(buffer);
        if(*buffer!=lb) return;//is a return true
        parseCommandFor(buffer);
        if(*buffer!=lb) return;//is a return true
        parseCommandExpression(buffer);
        if(*buffer!=lb) return;//is a return true
        parseCommandBlock(buffer);
        if(*buffer!=lb) return;//is a return true
    }//is a return false
    


  • Liq schrieb:

    Ich dachte eigentlich, das es in C so keine Call by Reference gibt?

    Gibt es auch nicht.
    In deinem Beispiel ist str eine lokale Variable, die eine Adresse von einem Objekt enthält. (call by value)
    Wenn du str veränderst, hat das keine Auswirkung auf die Adresse von dem Objekt.

    Du kannst aber den Inhalt an der Adrese verändern und änderst somit auch das Objekt.

    Also ist eine Antwort:
    Du brauchst Pointer, um call by reference zu simulieren.

    Liq schrieb:

    Kann ich das also so richten, das der Buffer bei der Übergabe an die zweite Methode auf dem Stand ist, auf dem er in der ersten am Ende war, ohne das ich den Buffer so als return Wert zurückgebe?

    Du kannst auch die Adresse von buffer an deine zweite Methode übergeben.
    Dann musst du aber die zweite Methode entsprechend anpassen.

    Schau dir mal den Paramter endptr bei strtol an: http://www.cplusplus.com/reference/cstdlib/strtol/



  • Liq schrieb:

    Erst einmal verstehe ich nicht ganz, wann man denn eigentlich konkret überhaupt Pointer braucht? Soweit ich weiß sind diese ja auf jeden Fall schon eimnal nützlich, wenn man etwas suchen will, bspw. in einem char * oder nicht?

    Zeiger sind Variablen, deren Wert als Adresse auf (die eigentlich interessanten) Daten interpretiert wird. Das passiert bei der Dereferenzierung.
    Zeiger müssen dereferenziert werden (*), um auf die zugrunde liegenden Daten (lesend UND schreibend) zugreifen zu können.
    Insbesondere wenn du Daten ändern willst und das (sauber gekapselt) über Funktionen (die eine Kopiersemantik für Parameter besitzen und somit ausschließlich call by value arbeiten) erreichen willst oder wenn du auf mehrere Datenelemente einer Gruppe die im Speicher direkt hintereinander liegen, zugreifen willst, verwendet man Zeiger.

    char * strcpy ( char * destination, const char * source );
    

    Hier übergibst du also eine (Beginn)Adresse auf einen Quell-Datenbereich und eine (Beginn)Adresse auf einen Ziel-Datenbereich, den Rest macht dann die Funktion. Du benötigst also nur eine Variable (den Zeiger) um auf mehrere Datenelemente zugreifen zu können.

    Liq schrieb:

    Ich habe auch oft gelesen, dass man Pointer nur dann verwenden sollte, wenn man wirklich muss aber wann muss man denn wirklich Pointer verwenden und wann nicht?

    Quatsch. s.o.

    Liq schrieb:

    Ich dachte eigentlich, das es in C so keine Call by Reference gibt?

    Gibt es auch nicht.

    int parseFile(char *buffer) {
        if(!parse_information1(&buffer))
            return 0;
        if(!parse_information2(&buffer))
            return 0;
        if(!parse_information3(&buffer))
            return 0;
    
        return 1;
    }
    Du musst nur
    int parse_information1(char *b)
    umbauen in
    int parse_information1(char **b)
    
    int alt(char *p)
    { /* gibt 1. Zeichen eines Strings aus und inkrementiert */
        putchar(*p);
        p++; /* diese Änderung am Zeiger schlägt wegen call by value NICHT bis zum aufrufenden Kontext durch */
        /* deswegen übergibt man einen Zeiger auf das betreffende Element und wenn das schon selbst ein Zeiger ist, dann wird es eben ein "Doppel"-Zeiger */
        return 1;
    }
    int neu(char **p)
    { /* gibt 1. Zeichen eines Stringzeigers aus und inkrementiert */
        putchar(*(*p)); /* p durch (*p) ersetzen */
        (*p)++;
        return 1;
    }
    void f(char *s)
    {
        alt(s);
        alt(s);
        alt(s);
        puts("\n========");
        neu(&s); /* "Doppel"-Zeiger */
        neu(&s); /* "Doppel"-Zeiger */
        neu(&s); /* "Doppel"-Zeiger */
    }
    int main()
    {
        f("Hallo");
        return 0;
    }
    

    http://ideone.com/UOEOAO


Log in to reply