別の関数でポインターを変更するには、複数の間接参照と呼ばれる概念が必要です。これについては後で説明します。@geofftnzを指定したスポイラーソリューションは複数の間接参照を使用します。私がやろうとしているのは、Cでの複数の間接参照を説明するために最善を尽くすことです。
次の2つのプログラムについて考えてみましょう。コードについて説明します。
次のプログラムは複数の間接参照を使用していないため、失敗します。
エラーのあるプログラム:
// 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;
}
上記のprogram()について考えてみましょう。このプログラムには、intを指すポインターでnoIndirection.c
ある変数があります。ptrMain
関数に渡された場合、関数の引数は一時変数であるため、関数scope(body)に一時ポインター変数が作成され、スコープ外になると削除されます。
一時ポインター変数(引数)は、関数に引数として渡されたときにptrTempAllctr
呼び出し元(main
)関数の変数ptrMain
(を指している)が指しているものを指します。NULL
malloc()
一時変数に別のポインターを使用または割り当てるptrTempAllctr
と、それがポイントさmain
れますが、to関数に引数として渡されたcaller()関数のポインター変数は、以前にallocater()
ポイントされたのと同じデータ( )をポイントします。NULL
関数呼び出し。
呼び出された(allocater()
)関数がスコープ外になると、一時ポインタ変数がスタックからポップされ、メモリが未割り当てのままになり、メモリリークが発生します。この制限を回避するには、複数の間接参照を使用する必要があります。
複数の間接参照:
Multiple indirection when we use of pointer/s to pointer/s in varying level(with multiple `*`) eg: `int **pp, int ***ppp`, etc.
&
そして、address-of( )演算子を使用してそれらを割り当てます。
複数の間接ポインター型変数が行うことは、上記のプログラムを修正するためのポインター変数自体へのポインターを作成できるようにすることです。
これにより、この呼び出しptrMain
を使用してのアドレスを渡すことができますallocater()
allocater(&ptrMain);
したがって、上記のプログラムnoIndirection.c
ではこれを行うことができませんwithIndirection.c
。この複数の間接参照を実装するプログラムを参照してください。
上記のバグのあるプログラム(noIndirection.c)を解決するには、この場合、関数のint **ptrMain
関数引数としてint pointer()へのポインターが必要です。allocater()
これは、次のプログラムで使用されました。
次のプログラムは、複数の間接参照を使用して、前のプログラムのバグを解決します。
// 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;
}
withIndirection.c
これからの参照のためにプログラムを参照してください。
この問題を解決するには、ポインタ変数ptrMain
(trueAllocater(&ptrMain);
)のアドレスをtrueAllocaterに渡すptrMain
必要がありtrueAllocater()
ます。これを行うには、関数が正しいレベルの間接ポインタを受け入れる必要があります。間接参照。これは、渡される変数の現在の理解に、引数宣言に追加された別の*を追加することです。
つまり、間接レベルが統計化されるように、ではなくinからのtrueAllocater()
関数引数を持つ必要があります。int **
int *
withIndirection.c
noIndirection.c
呼び出し元の引数変数ptrMain
のアドレスが関数に渡されたとき。関数内の一時ptrTrueAllocater
引数変数は、(プログラム内にある)ポインター変数がfunction()内で指しているものではなくptrMain
、caller(main
)関数内のポインター変数のアドレスを指している。ptrMain
NULL
main
変数を逆参照すると、一時変数がその内容ではなくcaller()変数自体を指しているため、指してptrTrueAllocater
いるアドレスptrMain
が明らかになります。ptrTrueAllocater
main
ptrMain
逆参照された変数の内容はptrTrueAllocater
、caller(main
)のvariable(ptrMain
)によってポイントされたデータのアドレスになるため、最終的なデータを取得するには、さらに1つの逆参照を実行する必要があります。
ptrMain
したがって、ポイントする必要のある場所を変更するために、ポイントするアドレスを取得するために1回逆参照する必要があります。また、であるptrMain
によってポイントされる実際のデータを取得するために2回逆参照する必要があります。ptrMain
NULL
@PaulWicksは変更するつもりだったので、ポインティングの場所を割り当てたり変更したりするには、一度参照を解除する必要があります。
ポインターを使用した複数の間接参照の目的は、多次元配列を作成し、何かを指す必要のあるポインター引数を渡すことです。
次のように操作する必要があるタイプに応じて変数を変更する必要があります。
宣言に*を追加するたびに、ポインターの間接レベルが増加し、逆参照するたびに、データに近づくポインターの間接レベルが減少します。
この問題は、必要なポインター変数を割り当てる呼び出し元関数にアドレスを返すことで解決できます。
はい、この多間接変数構文を使用して、1次元または多次元の配列を作成できます。これは初心者を最初は混乱させるでしょう、彼らがたくさんのコードを読むのに時間をかけるならば、彼らはそれらの間の違いを見つけることができるでしょう。
私が間違っている場合は訂正してください。フィードバックを提供し、複数の間接ポインターのその他の使用法を教えてください。私の悪い英語をお詫びします。これらは、複数の間接的な方法を理解するのに役立つリソースです。
https://boredzo.org/pointers/#function_pointers
https://cseweb.ucsd.edu/~ricko/rt_lt.rule.html