Pointer in Funktion neu definieren - geht nicht!
-
Hallo, ich hab hier eine seltsame Begebenheit:
#include <stdlib.h> #include <stdio.h> typedef struct struct__ { char *pointer; } struct__; void setStruct(char *pointer) { pointer=0x12345678; } int main() { struct__ *s=malloc(sizeof(struct__)); s->pointer=NULL; if(s == NULL) { printf("error1\n"); return 1; } printf("%p\n",s->pointer); setStruct(s->pointer); printf("%p\n",s->pointer); free(s); return 0; }
Ausgabe:
00000000
00000000Gewünschte Ausgabe:
00000000
12345678Hab ich hier beim C-lernen irgendwas nicht mitbekommen? Warum kann ich den char-pointer nicht in der Funktion neu definieren?
-
Aus dem gleichen Grund, warum folgendes nicht geht:
void aendern(int i) { i = 5; } int main() { int foo = 0; aendern(foo); // foo ist immer noch 0 }
"Aber!", wendest du nun ein "ich habe hier einen Zeiger benutzt und mit Zeigern funktioniert das:"
void aendern(int *i) { *i = 5; } int main() { int foo = 0; aendern(&foo); // foo ist nun 5 }
Und das funktioniert so tatsächlich. Jedoch gibt es einen wichtigen Unterschied: Du hast nicht den Zeiger verändert. Du hast verändert, worauf er zeigt! Genauso musst du das auch machen, wenn du einen Zeiger selber in einer Funktion ändern möchtest. Du brauchst dann eben einen Zeiger auf den zu ändernden Zeiger, über den du den ursprünglichen Zeiger ändern kannst.
-
c=c+1; schrieb:
Hab ich hier beim C-lernen irgendwas nicht mitbekommen? Warum kann ich den char-pointer nicht in der Funktion neu definieren?
Da bin ich doch mal dankbar für die Frage.
Ja, du hast was nicht mitbekommen. Nämlich die essentielle C-Grundlage, dass Funktionsparameter ausschließlich percall by value
übergeben werden.
Das gilt natürlich auch für Zeiger. Auch der Wert des Zeigers (Adresse) wird kopiert, bevor er an den Funktionsrumpf übergeben wird.
Deshalb ist auch sämtliches Geplapper voncall by reference in C Schwachsinn
.
Genau deswegen kannst du Änderungen innerhalb der Funktion am Parameter direkt machen soviel du willst, du siehst ja, der aufrufende Kontext bleibt davon unbeeindruckt.
-
Pointer wird bei setStruct per Kopie uebergeben, d.h. du aenderst nur die Kopie.
-
Noch ein paar Kommentare zu deinem Programm:
-Wenn du in Zeile 8 dein kapselndes struct benutzen würdest, anstatt einem rohen Zeiger, hätte es gleich funktioniert.
-Zeile 14: Es gilt als allgemein besser, bei einem sizeof den Typ aus dem Variablennamen herzuleiten:foo *bar = malloc(X*sizeof(foo));
->
foo *bar = malloc(X*sizeof(*bar));
So kann später der genaue Typ von bar zu etwas anderem als foo geändert werden (ein Vorgang der durchaus vorkommt), ohne dass man den sizeof-code ändern braucht.
-In Zeile 15 dereferenzierst du fröhlich deinen Zeiger, obwohl du erst in Zeile 16 prüfst, ob solch eine Aktion überhaupt gültig wäre.printf("error1\n");
->puts("error1");
. Hier sicherlich nicht wichtig, aber gewöhn es dir richtig an. puts/putchar sind viel schneller als das fette printf für einzelne Zeichen(ketten) zu benutzen.
-Die Idee, einen Pointer auf einen festen Wert zu setzen ist ziemlich wild. Ich hoffe mal, das ist bloß ein Beispiel.
-
Alles klar, danke.