ausgabe bei kommandozeilenargument



  • Welche Ausgabe hat folgendes Programm, wenn man es mit dem Kommandozeilenargument GSVCPD aufruft?
    Erläutern Sie, wie es zu dieser Ausgabe kommt.
    01 #include <stdio.h>
    02 #include <string.h>
    03
    04 int main(int argc, char *argv[])
    05 {
    06 char **pp, *z;
    07 if (argc > 1)
    08 {
    09 pp = argv + 1;
    10 z = *pp + strlen(*pp);
    11
    12 while (*pp - --z)
    13 printf("%c", --*z);
    14
    15 printf("%c\n", *z);
    16 }
    17 return 0;
    18 }
    

    pp zeigt ja auf GSVCPD
    bei z wird es schon schwieriger... *pp wäre ja G?! und dann + strlen(*p)?
    is das dann derefernziert die länge von G bzw. 1?

    die bedinung in der while schleife is mir auch net ganz klar...
    kann mir da vielleicht jmd helfen?
    gruss pete

    edit: ich weiss was raus kommt, nur möchte ich drauf kommen 🙂



  • p ist ein Zeiger auf einen char*, *p ist der char* dahinter (und verweist auf das erste (und einzige) übergebene Argument "GSVCPD") - mit strlen() holst du dir die Länge dieses Arguments (6). Damit wird z auf den Null-Terminator des Argument-Strings gesetzt (und läuft in der Schleife schrittweise zurück).

    Zur while-Schleife:
    "--z" dekrementiert z und liefert dessen neuen Wert zurück
    "*p - --z" bildet den Abstand zwischen den beiden Zeigern (am Anfang 5, am Ende 0 - was als false interpretiert wird und die Schleife beendet)

    (und das "--*z" verringert den Zeichenwert im Argumentstring, bevor er ausgegeben wird)



  • beim ersten durchlauf:
    hätte ich ja dann in der whileschleife die bedingung: G-D != 0 , was bedeutet, dass er
    rein läuft.
    dann gib ich das erste zeichen aus... wäre ein P ... müsste aber doch ein C sein... also nochmal dekrementiert???

    ist die whileschleife = 0, wenn z dann P angekommen ist?! wäre ja dann 0...
    auch wenn man die ascii werte benutzt und voneinander abzieht.



  • Da werden nicht die Inhalte hinter den Zeigern verrechnet, sondern die Zeiger-Adressen. Prinzipiell kannst du dir das so vorstellen:

    //vor dem Beginn der while-Schleife:
    
    pp->argv[1]
          |
          v
        [ G | S | V | C | P | D |\0 ]
                                  ^
                                  |
    z ----------------------------+
    
    -> pp - z = -6
    
    //Abfrage der while-Schleife:
    
    pp->argv[1]
          |
          v
        [ G | S | V | C | P | D |\0 ]
                              ^
                              |
    z ------------------------+
    
    -> pp - --z = -5 (parallel wird z umgebogen)
    
    //Ausgabe in der Schleife:
    
    pp->argv[1]
          |
          v
        [ G | S | V | C | P | C |\0 ]
                              ^
                              |
    z ------------------------+
    
    -> --*z dekrementiert jetzt tatsächlich den Wert in deinem Argumentstring (aus 'D' wird 'C')
    -> der neue Inhalt von *z ('C') wird ausgegeben
    

    (in den weiteren Schleifendurchläufen wird auf die selbe Art 'O','B','U','R' ausgespuckt - und nach der Schleife das 'G' vom Anfang des übergebenen Arguments.

    (du stammst nicht zufällig aus Coburg, oder?)



  • ja doch... genau aus coburg 🙂
    habe die dereferenzierung bei der printf anweisung nicht beachtet gehabt, weshalb ich noch ne stelle im kommandozeilenargument geschoben habe.
    vielen dank für deine ausführliche hilfe! 🙂



  • dahier hätte ich noch eins:

    #include <stdio.h>
    char *c[] =
    {
    "he dast ga",
    "lllt dumm",
    "C i",
    "dar nich"
    };
    char **cp[] = { c+3, c+2, c+1, c };
    char ***cpp = cp;
    int main( void )
    {
    printf( "%s", **++cpp );
    printf( "%s", *--*++cpp+5 );
    printf( "%s", cpp[-2][0]+2 );
    printf( "%s\n", *(cpp[1]+1)+3 );
    getchar();
    }
    

    da weiss ich nicht genau, was ich mit:

    printf( "%s", --++cpp+5 );

    machen soll.

    da +cpp auf "C i" zeigt und dann
    --++cpp+5 zuerst dekrementiert, dann inkrementiert und dann +5?
    inkrement und dekrement würde sich doch gegenseitig aufheben?!...
    trotzdem er dann nicht auf "t ga"



  • Na gut, nehmen wir den Ausdruck mal auseinander:
    --++cpp+5 -> ((--((++cpp))))+5

    Ausgangsbedingung: cpp verweist auf cp[1], dieses wiederum auf c[2]="C i"

    (++cpp) - verbiegt cpp auf cp[2] -> c[1] = "lllt dumm"
    (++cpp) - dereferenziert cpp - d.h. wir arbeiten nun mit cp[2] weiter
    --(
    (++cpp)) - verbiegt cp[2] auf c[0] = "he dast ga"
    (--((++cpp))) - dereferenziert cp[2] - d.h. wir arbeiten mit c[0] weiter
    ((--((++cpp))))+5 - geht fünf Schritte nach vorne - damit haben wir einen Zeiger auf das 6. Zeichen von cp[0] (das ist das s)

    -> die Ausgabe liefert "st ga"

    (die Zeigerbiegereien im ersten und dritten Schritt bleiben auch für die folgenden Ausgaben erhalten)



  • (++cpp) - dereferenziert cpp - d.h. wir arbeiten nun mit cp[2] weiter
    --(
    (++cpp)) - verbiegt cp[2] auf c[0] = "he dast ga"

    d.h. wenn ich dereferenziere, arbeite ich nicht mehr mit dem aktuellen zeiger, sondern geh eine stufe tiefer und verwende den dann weiter?!



  • Ja, das ist der Zweck des Dereferenzierens - du gehst von einem Zeiger zu dem Wert, auf den er gerade zeigt.


Log in to reply