011
15.09.2005, 13:18 Uhr
Pablo
Supertux (Operator)
|
Zitat von netdisaster: |
Du Gott der Nullen und Einsen! Es läuft.
|
Hier ist Beefy Gott. A propo beefy, was ist aus ihm geworden?
Zitat von netdisaster: |
Warum genügt es nicht, quasi nur die Speicheradresse des reservierten Speichers per Pointer weiterzugeben. Warum muss ich den ganzen Pointer als cbr durchreichen. Und meine realloc-Funktion ist doch in cr_newMONT, die ich nur von main() über poco_mont() erreiche. Wieso muss ich da nicht "MONTAGEFOLGE ***MONT_List" als Parameter setzen.
|
das liegt daran, dass Zeiger auch nur Variablen sind. Zeiger sind Variablen, die ein Adresse speichern, nämlich die Adresse auf die ein Zeiger zeigt. Guck dir diesen Code hier an
C++: |
void add(int a, int b, int c) { c = a + b; }
void foo() { int a = 6; int b = 8, c = 0;
add(a,b,c); printf("add(%d, %d) = %d\n", a, b, c); }
|
Du wirst sofort sagen, dass die Ausgabe add(6,8,0) ist, und das ist richtig, denn die Adresse der Variable foo::c ist nicht unter add bekannt und add::c ist nur ein Kopie von foo::c. D.h. add::c hat nur den Wert von foo::c aber sie sind 2 unterschiedliche Variablen und die Änderungen von add::c sind unter allen anderen Funktion unsichtbar.
Was muss man machen, damit eine andere Funktion den Wert einer Variable einer anderen Funktion ändern kann? Da kommen die Zeiger ins Spiel. Ein Zeiger ist nicht anders als soz. eine int Variable deren Inhalt die Adresse im Speicher einer anderen variable ist.
C++: |
int var = 8; int* zeiger_auf_var = &var;
|
welchen Wert zeiger_auf_var speichert ist vom Speicherort von var abhängig. Nehmen wir an, var befindet sich unter 0xdeadbeef. Dann speichert die Variable zeiger_auf_var den Wert 0xdeadbeef. Somit kann man direkt auf den Speicher zugreifen und ihn nach Bedarf ändern.
C++: |
int var = 8; int* zeiger_auf_var = &var; zeiger_auf_var = ????;
|
ändert nicht den Wert von var auf ??? sondern lässt den Zeiger auf eine andere Adresse ziegen, während
C++: |
int var = 8; int* zeiger_auf_var = &var; *zeiger_auf_var = ????;
|
sorgt dafür, dass der Wert von var auf ??? geändert wird. Warum? Weil man mit *zeiger_auf_var direkt auf den Speicher durch die Speicheradresse zugreifen können. Wenn wir bei der Annahme geblieben sind, dann bedeutet das quasi: "Weise den Wert ??? dem Speicherort 0xdeadbeed zu". Somit erzeugt folgender Code das gewünschte:
C++: |
void add(int a, int b, int* c) { *c = a + b; }
void foo() { int a = 6; int b = 8, c = 0;
add(a,b,&c); printf("add(%d, %d) = %d\n", a, b, c); }
|
Alternativ wäre
C++: |
int* zeiger = &c; add(a,c,zeiger); ...
|
So, beim neuen Code sind foo::c und add::c natürlich unterschiedlich, wie gesagt nur eine Kopie des Inhalts der Variable foo:c. Aber da add::c ein Zeiger ist, kann man durch ihn auf eine Speicheradresse direkt zugreifen. Und somit kann add::c den Wert von add::c ändern.
Nun, mit Doppelzeiger ist es genau dasselbe. Malloc-Family Funktionen liefern ein void* zurück, d.h. ein Zeiger. realloc liefert ebenfalls einen Zeiger.
C++: |
void change(int* zeig, size_z len) { int* tmp = realloc(zeig, len); if(!tmp) .... if(tmp != zeig) zeig = tmp; }
void foo() { int* etwas;
etwas = malloc(sizeof(int)*10);
if(!etwas) ...
change(etwas, sizeof(int)*100); }
|
so, hier verhält es sich um change::zeig genau so wie im ersten Beispiel. Wenn change aufgerufen wird und sagen wir mal, realloc eine Adresse liefert, die unterschiedlich mit der alten ist, dann muss der Zeiger geändert werden, da tue ich auch mit "if(tmp != zeig) zeig = tmp;". Spätestens jetzt sollte dir klar sein, dass das in die Hose geht, denn zeig = tmp; heißt, ändere den Zeiger von zeig, sprich ändere den gespeicherten Wert von der Variable zeig. Wenn du Funktion verlassen wird, so ist diese Änderung für foor unsichtbar, genauso wie oben. Da du den Inhalt des Zeigers und nicht der gezeigten Adresse ändern willst, musst du die Adresse des Zeigers liefern, also
C++: |
void change(int** zeig, size_z len) { int* tmp = realloc(*zeig, len); if(!tmp) .... if(tmp != *zeig) *zeig = tmp; }
void foo() { int* etwas;
etwas = malloc(sizeof(int)*10);
if(!etwas) ...
change(&etwas, sizeof(int)*100); }
|
so, hast du es verstanden? -- A! Elbereth Gilthoniel! silivren penna míriel o menel aglar elenath, Gilthoniel, A! Elbereth! |