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