Verständnisprobleme mitm Pointer auf Stringarrays



  • Hi,

    ich versuche mir C in den Grundzügen reinzuziehen und grübele nun schon länger über folgendes Problem.

    Folgendes ist mir klar:

    int i = 5;
      int *p = &i;
      printf("*p = %d\n", *p);
    

    Ich muss beim printf natürlich *p machen, da ich bei p (ohne 😉 ja versuche die Adresse auszugeben.

    Anderes Beispiel mit strings:

    char *z[3] = {"das", "istein", "test"}; 
      char *p = z[1];
      printf("! z[2]: %s\n", z[2]); 
      printf("! p: %s\n", p);
    

    Nun habe ich damit so meine Probleme. Folgendes:
    Ich ging davon aus, dass in z[] die Anfangsadressen stehen, wo dann die drei Stringarrays im Speicher stehen. Daher wäre es nach meinem Verständnis eigentlich auch falsch, dass z[2] wirklich "test" ausgibt. Ich hätte erwartet, ich muss mit *z[2] arbeiten.
    Dann mein zweites Problem: Dass die zweite Zeile funktioniert, hab ich mir so erklärt: In z[1] steht die Anfangsadresse für "istein", daher handelt es sich ja schon um eine Adresse und ich benötige keinen &-Operator wie in Beispiel eins. Aber bei der Ausgabe von p hätte ich nun auch wieder ein *p erwartet, weil in p doch nur eine Adresse steht?!

    Wo liegt mein Denkfehler, wo ist da das "Besondere" an den Pointern auf Stringarrays? Es wär schön direkt eine Antwort auf mein Problem zu erhalten, und keinen Link zu irgendeinem Pointer-Tutorial. Davon habe ich schon so einige gelesen aber so richtig lösen konnte ich mein Problem damit nicht 😞

    Danke für eure Hilfe!



  • Zu Problem 1:
    Du hast Recht, in z[] stehen die Anfangsadressen der drei Worte.
    Das Geheimnis liegt hier in %s: %s erwartet einen Pointer auf char
    und gibt den Speicher ab dem Pointer solange aus, bis es auf das erste
    Char mit Wert 0 trifft.

    Zu Problem 2:
    Auch hier wieder: s.o.

    Gruß mcr



  • printf("! z[2]: %s\n", &z[2]);
    printf("! p: p\n", &p);
    

    Wieso will dann das hier nicht funktionieren?



  • Weil &z[2] die Adresse der Stelle ist, an der die Adresse des dritten Strings liegt.
    Weil &p die Adresse der Stelle ist, an der die Adresse des Strings liegt.



  • Ganz kurz nochmal:

    *p ist er Inhalt der Speicherstelle
    &p die Adresse der Speicherstelle
    p die Speicherstelle selbst?



  • noch ne frage schrieb:

    Ganz kurz nochmal:

    *p ist er Inhalt der Speicherstelle
    &p die Adresse der Speicherstelle
    p die Speicherstelle selbst?

    int a = 10;      //a, belegt irgendwo Speicher. Der Speicher wird als int interpretiert und enthält den Wert 10
    int* p_a = &a;   //p_a zeigt auf die Speicherstelle von a (p_a belegt selbst an anderer Stelle Speicher und dieser Speicher wird als Pointer auf int interpretiert)
    *p_a = 50;       //ändert den Wert der Speicherstelle auf den p_a zeigt
    printf("%i\n", a); //Gibt 50 aus
    


  • noch ne frage schrieb:

    Ganz kurz nochmal:

    *p ist er Inhalt der Speicherstelle
    &p die Adresse der Speicherstelle
    p die Speicherstelle selbst?

    Wenn p ein Zeigertyp ist, dann:
    *p ist der Inhalt der Speicherstelle, auf die p zeigt
    p (der Wert) ist die Adresse der Speicherstelle, auf die p zeigt
    &p ist die Adresse der Speicherstelle, an der die Adresse der Speicherstelle steht, auf die p zeigt.

    Da jeder Zeiger (also die Adresse) selbst irgendwo im Speicher stehen muss, kann man auf jeden Zeiger wiederum einen Zeiger bilden.



  • noch ne frage schrieb:

    *p ist er Inhalt der Speicherstelle
    &p die Adresse der Speicherstelle
    p die Speicherstelle selbst?

    wenn du das 'p' aus dem code oben^^ meinst, dann ...
    ... ist p ein pointer, also eine variable, die eine adresse beinhaltet.
    ... ist *p ein zugriff auf die adresse, auf die der pointer zeigt.
    ... ist &p die adresse der pointers selbst.
    🙂



  • mcr schrieb:

    Zu Problem 1:
    Das Geheimnis liegt hier in %s: %s erwartet einen Pointer auf char

    Ahh, so einfach kanns sein. Vielen dank 🙂



  • Demnach müsste doch (belVar *)&p das gleiche sein wie p? Denn &p ist die Adresse des Pointers und mit dem Cast (belVar 😉 greift man auf den Inhalt von &p zu. Oder?



  • noch ne frage schrieb:

    Demnach müsste doch (belVar *)&p das gleiche sein wie p? Denn &p ist die Adresse des Pointers und mit dem Cast (belVar 😉 greift man auf den Inhalt von &p zu. Oder?

    (belVar 😉 &p ist das gleiche wie &p, es hat nur einen anderen Typ. Mit Casts änderst Du nur den Typ eines Ausdrucks. Auf den Inhalt von &p greifst Du mit *&p zu. *&p ist identisch zu p.



  • Ich komme dabei aber noch einer nächsten Frage:

    char z[3][10] = {"das", "istein", "test"}; 
      printf("! z[2]: %s\n", z[2]);
      printf("! z[2]: %s\n", &z[2]);
    

    Also array direkt angelegt, ohne pointer. Der printf-Befehl sieht allerdings genauso aus, und funktioniert auch genauso. Warum ist das offenbar trotzdem ein Pointer, obwohl z anders deklariert wurde? Und warum funktionierte die dritte Zeile genauso?



  • Vielen Dank!



  • noch ne frage schrieb:

    Demnach müsste doch (belVar *)&p das gleiche sein wie p?

    Nein! Es ist derselbe Wert wie &p



  • flowschi schrieb:

    Ich komme dabei aber noch einer nächsten Frage:

    char z[3][10] = {"das", "istein", "test"}; 
      printf("! z[2]: %s\n", z[2]);
      printf("! z[2]: %s\n", &z[2]);
    

    Also array direkt angelegt, ohne pointer. Der printf-Befehl sieht allerdings genauso aus, und funktioniert auch genauso. Warum ist das offenbar trotzdem ein Pointer, obwohl z anders deklariert wurde? Und warum funktionierte die dritte Zeile genauso?

    Noch eine Ergänzung hierzu:

    Kann ich char *z[3] auf jedenfall durch z[3][10] ersetzen (sofern 10 ausreichend sind), und alle andern Befehle und Ausgaben funktionieren noch genauso?



  • flowschi schrieb:

    Ich komme dabei aber noch einer nächsten Frage:

    char z[3][10] = {"das", "istein", "test"}; 
      printf("! z[2]: %s\n", z[2]);
      printf("! z[2]: %s\n", &z[2]);
    

    Also array direkt angelegt, ohne pointer. Der printf-Befehl sieht allerdings genauso aus, und funktioniert auch genauso. Warum ist das offenbar trotzdem ein Pointer, obwohl z anders deklariert wurde? Und warum funktionierte die dritte Zeile genauso?

    Wenn du in C ein Array deklarierst und initialisierst(mit einem Wert belegst), dann macht der Compiler nichts anderes als für die Werte einen zusammenhängenden Speicherplatz zu reservieren und einen Pointer auf den Anfang von diesem Speicherplatz zu setzten.

    (Zusammenhängend heißt: die Speicherstellen, die mit den Werten belegt sind liegen alle strikt beieinander und _nicht_ ein Wert irgendwo im "Anfang" des Speicher und eins am "Ende". )


Log in to reply