Zeigeradresse ändert sich bei Übergabe



  • Guten Abend,
    ich habe ein seltsames Problem mit meinen Zeigern. Folgendes Szenario liegt zugrunde:

    /* main.h */
    #ifndef ...
    typedef struct _type1{
    char* name;
    int type;
    } type1;
    
    typedef struct _type1_list {
    type1 **tlist;
    int count;
    } type1_list;
    
    struct st {
    type1_list *list;
    char* whatever;
    };
    #endif
    

    Weiter mit der Initialisierung

    /* main.c */
    #include "main.h"
    #include "fill_whatever.h"
    
    struct st * st_ptr = NULL;
    
    st_ptr = (struct st *) malloc(sizeof(struct st)); //ich weiss: kann NULL sein
    st->list = NULL;
    printf("address of list=%d\n", &(st->list));
    st->whatever = NULL;
    
    fill_whatever(st);
    

    Nun eine Funktion, welche dem Zeiger 'whatever' die Adresse eines eines allokierten Strings zuweist und den Zeiger 'list' zur Befüllung weitergeben soll.

    /* fill_whatever.c */
    #include "fill_whatever.h"
    #include "fill_list.h"
    void fill_whatever(struct st *st_ptr){
    st_ptr->whatever = strdup("whatever");
    printf("address of list=%u\n", &(st_ptr->list); //gleiche Adresse wie in main.c
    fill_list(st_ptr->list);
    }
    

    Wenn ich nun folgendes mache

    /* fill_list.c */
    #include "main.h"
    void fill_list(type1_list *list){
    printf("address of list=%u\n", &list); //andere Adresse als in main.c
    }
    

    Somit geht natürlich der eigentliche Call by Reference Gedanke verloren und ich arbeite in 'fill_list()' auf irgendeiner anderen Speicheradresse. Seltsamerweise gibt es keinerlei Beanstandungen seitens des Compilers.

    Sieht jemand meinen Fehler ?

    Besten Dank im Voraus!

    Gruss, Michi



  • noch_ein_michi schrieb:

    Wenn ich nun folgendes mache

    /* fill_list.c */
    #include "main.h"
    void fill_list(type1_list *list){
    printf("address of list=%u\n", &list); //andere Adresse als in main.c
    }
    

    ist logisch, dass die Adresse anders ist, denn 'list' zeigt auf die selbe Stelle wie 'st_ptr->list' (sprich, der Inhalt von 'list' ist 'st_ptr->list') aber die lokale Variable 'list' der fill_list Funktion liegt ganz wo anders als st_ptr->list und genau diese Adressen gibst du per printf aus, nicht die Adressen, worauf beide Pointer wirklich zeigen.

    // edit:

    ändere deine Printfs so:

    printf("saved address of list=%d\n", st->list);
    printf("saved address of list=%u\n", st_ptr->list; //gleiche Adresse wie in main.c 
    printf("saved address of list=%u\n", list); //gleiche Adresse wie in main.c
    


  • Hallo supertux,
    vielen Dank für die Antwort.

    Es geht mir aber nicht um das printf() an sich. Mein Ziel ist es, dass die Funktion fill_list() tatsächlich den Wert an der Speicheradresse von st_ptr->list ändert, also den Wert auf den str_ptr->list zeigen soll. st_ptr->list wird ja mit NULL initialisiert und somit zeigt st_ptr->list zum Zeitpunkt der Übergabe noch nicht wirklich auf etwas.

    Es muss also ein Unterschied darin liegen, ob ich einen Struktur Pointer übergebe (wie es von main() nach fill_whatever() passiert -> dort bleibt die Adresse des Struktur Pointers gleich -> keine lokale Kopie ?) oder ich ein Member des Pointers übergebe.

    Wo liegt der Trick bei der Sache ? Macht es einen Unterschied, dass type1_list als eigener Datentyp definiert und st 'nur' als struct ?

    Wäre Klasse, wenn Du/Ihr Euch noch einmal erbarmen könntet.

    Beste Grüsse

    Michi



  • Da gibts keinen Trick. st->list und die lokale Variable list in fill_list sind unterschiedliche Pointer, die auf dasselbe zeigen (können). Deshalb haben sie auch unterschiedliche Adressen. Punkt aus 😉

    Wenn Du ändern möchtest, worauf der Zeiger list in der Struktur st zeigt, musst Du den Zeiger selbst "by-reference" übergeben, damit Änderungen am Zeiger in der Funktion nach der Rückkehr Wirkung zeigen:

    void fill_list(type1_list **list){
        printf("address of list=%p\n", list); //jetzt selbe Adresse wie in main.c
        *list = malloc(...); // benutzen
    }
    


  • LordJaxom schrieb:

    Wenn Du ändern möchtest, worauf der Zeiger list in der Struktur st zeigt, musst Du den Zeiger selbst "by-reference" übergeben, damit Änderungen am Zeiger in der Funktion nach der Rückkehr Wirkung zeigen:

    void fill_list(type1_list **list){
        printf("address of list=%p\n", list); //jetzt selbe Adresse wie in main.c
        *list = malloc(...); // benutzen
    }
    

    Ganz hervorragend ! Das klappt einwandfrei! Besten Dank für die Antwort. Damit ist das Problem gelöst.

    Gruss, Michi


Log in to reply