Das Ändern eines Zeigers in einer anderen Funktion erfordert ein Konzept namens multiple Indirektion, ich werde es später erklären, die Spoilerlösung von @geofftnz verwendet multiple Indirektion. Ich versuche mein Bestes, um die mehrfache Indirektion in C zu erklären.
Betrachten Sie die folgenden zwei Programme, ich werde durch den Code gehen.
Das folgende Programm verwendet keine Mehrfachumleitung und schlägt daher fehl.
Programm mit Fehler:
// filename: noIndirection.c
#include <stdio.h>
#include <stdlib.h>
void allocater(int *ptrTempAllctr)
{
ptrTempAllctr = malloc(sizeof(int));
if (ptrTempAllctr == NULL) {
perror("in allocater() memory allocation error");
exit(EXIT_FAILURE);
}
}
int main()
{
int *ptrMain = NULL;
allocater(ptrMain);
if (ptrMain == NULL) {
printf("ptrMain is points to NULL\n");
return 1;
}
//free(ptrMain); // we don't have to free because it will be invalid free.
return 0;
}
betrachten Sie das obige Programm( noIndirection.c
), die eine Variable hat ptrMain
es ist ein Zeiger, der auf einen int zeigt. Wenn er an eine Funktion übergeben wurde, wird im Funktionsbereich (body) eine temporäre Zeigervariable erstellt, da Argumente der Funktion temporäre Variablen sind, die gelöscht werden, wenn sie den Funktionsbereich verlassen.
Die temporäre Zeigervariable ptrTempAllctr
(das ein Argument ist) wird auf das verweisen, was auch immer der Aufrufer( main
) die Variable der Funktion ptrMain
(die auf NULL
) zeigte, als es als Argument an die Funktion übergeben wurde.
Wenn wir die malloc()
oder einen anderen Zeiger auf die temporäre Variable zuweisen ptrTempAllctr
dann zeigt er darauf, aber die Zeigervariable in caller( main
) Funktion, die als Argument an die to-Funktion übergeben wurde allocater()
immer noch auf die gleichen Daten verweist (die NULL
), auf die er vor dem Funktionsaufruf gezeigt hat.
Wenn der aufgerufene ( allocater()
) wird die temporäre Zeigervariable aus dem Stack entfernt und der nicht zugewiesene Speicher wird durch ein Speicherleck ersetzt. Um diese Einschränkung zu umgehen, müssen wir mehrere Umleitungen verwenden.
MEHRFACHE UMLEITUNG:
Multiple indirection when we use of pointer/s to pointer/s in varying level(with multiple `*`) eg: `int **pp, int ***ppp`, etc.
und wir weisen sie mit address-of( &
) Betreiber.
Die Variablen des Typs "Multiple Indirection Pointer" ermöglichen es uns, eine einen Zeiger auf eine Zeigervariable selbst zu machen, um das obige Programm zu fixieren. Dies erlaubt uns, die Adresse der ptrMain
zu allocater()
mit diesem Aufruf
allocater(&ptrMain);
also das obige Programm noIndirection.c
dies nicht zulässt, siehe das Programm withIndirection.c
um diese mehrfache Umleitung zu implementieren.
Wir brauchen einen Zeiger auf int pointer( int **ptrMain
) als Funktionsargument für allocater()
Funktion in diesem Fall, um das obige fehlerhafte Programm (noIndirection.c) zu lösen.
Dies wurde in dem folgenden Programm verwendet.
Das folgende Programm verwendet Mehrfachumgehung um den Fehler im vorherigen Programm zu beheben.
// filename: withIndirection.c
#include <stdio.h>
#include <stdlib.h>
void trueAllocater(int **ptrTrueAllocater)
{
*ptrTrueAllocater = (int *) malloc(sizeof(int));
if (ptrTrueAllocater == NULL) {
perror("in trueAllocater() memory allocation error");
exit(EXIT_FAILURE);
}
}
int main(void)
{
int *ptrMain = NULL;
trueAllocater(&ptrMain);
if (ptrMain == NULL) {
printf("memory not allocated\n");
return EXIT_FAILURE;
}
printf("memory allocated and assigned to ptrMain");
printf(" from trueAllocater\n");
free(ptrMain);
return EXIT_SUCCESS;
}
siehe das Programm withIndirection.c
als Referenz von nun an.
Um unser Problem zu lösen, müssen wir die Adresse der Zeigervariablen übergeben ptrMain
( trueAllocater(&ptrMain);
) an den trueAllocater, um die ptrMain
wohin sie später in den folgenden Abschnitten zeigen muss trueAllocater()
oder eine andere Funktion, Dazu muss die Funktion einen Umleitungszeiger mit der richtigen Umleitungsebene akzeptieren, was bedeutet, dass der Argumentdeklaration für die übergebenen Variablen ein weiterer * hinzugefügt werden muss, um mein derzeitiges Verständnis zu verbessern.
Dazu benötigen wir die trueAllocater()
Funktionsargument als int **
von int *
in withIndirection.c
im Gegensatz zu noIndirection.c
damit die Umleitungsebene statistisch erfasst wird.
Wenn die Adresse der Argumentvariablen des Aufrufers ptrMain
Adresse an die Funktion übergeben wurde. die temporäre ptrTrueAllocater
Argumentvariable in Funktion zeigt auf die Adresse der Zeigervariablen ptrMain
Adresse in caller( main
) Funktion nicht welche Zeigervariable ptrMain
(das ist NULL
im Programm) zeigt auf in function( main
).
Wenn wir die Dereferenzierung der ptrTrueAllocater
Variable die Adresse, die ptrMain
wird offenbart werden, weil die ptrTrueAllocater
temporäre Variable zeigt auf den Aufrufer( main
) ptrMain
Variable selbst, nicht ihren Inhalt.
Der Inhalt des dereferenzierten ptrTrueAllocater
ist die Adresse der Daten, auf die der Aufrufer zeigt( main
) ist die Variable( ptrMain
), also müssen wir eine zusätzliche Dereferenzierung durchführen, um die endgültigen Daten zu erhalten.
also müssen wir einmal dereferenzieren, um die Adresse der ptrMain
auf die er zeigt, um den Ort zu ändern ptrMain
muss gezeigt und dereferenziert werden zweimal, um die tatsächlichen Daten zu erhalten, auf die die ptrMain
das ist NULL
.
@PaulWicks Sie beabsichtigt, zu ändern, so dass Sie zu dereferenzieren einmal zuzuweisen oder zu ändern, wo seine zeigen.
Die Absicht der mehrfachen Umleitung mit Zeigern ist es, mehrdimensionale Arrays zu erstellen und Zeigerargumente zu übergeben, die auf etwas gezeigt werden müssen.
Wir müssen die Variable entsprechend den Typen, die wir manipulieren müssen, wie folgt ändern,
jede Hinzufügung von * in der Deklaration erhöht den Grad der Zeigerumlenkung und jede Dereferenzierung verringert die Zeiger-Indirektionsebene, d.h. sie führt zu einer Annäherung an die Daten.
Wir können dieses Problem lösen, indem wir die Adresse an die aufrufende Funktion zurückgeben und der erforderlichen Zeigervariablen zuweisen.
Ja, wir können diese Multi-Indirektions-Variablen-Syntax zur Erstellung von ein- oder mehrdimensionalen Arrays verwenden. Dies wird Anfänger zunächst verwirren, aber wenn sie sich Zeit nehmen, um Zeit investieren, um viel Code zu lesen, werden sie in der Lage sein, den Unterschied zwischen ihnen zu erkennen.
Bitte korrigieren Sie mich, wenn ich falsch liege, geben Sie mir Feedback und lassen Sie mich wissen, was die andere Verwendungszwecke von mehrfachen Indirektionszeigern. Entschuldigung für mein schlechtes Englisch. Dies sind die Ressourcen, die mir geholfen haben, multiple indirections zu verstehen. https://boredzo.org/pointers/#function_pointers https://cseweb.ucsd.edu/~ricko/rt_lt.rule.html