配列へのポインターを参照して、そこに格納されている値を取得するにはどうすればよいですか? 例えば:
void testFunction(int **test){
printf("%d", *test[1]);
}
int main()
{ int test[10];
test[1] = 5;
testFunction(&test);
return 0;
}
エラーが発生します。誰でも説明できますか?
配列へのポインターを参照して、そこに格納されている値を取得するにはどうすればよいですか?
*
すべてのポインターと同様に、演算子を使用します。(ああ、演算子の優先順位に注意してください!)
void foo(int (*arr)[5])
{
printf("%d\n", (*arr)[0]);
}
int main()
{
int arr[5] = { 0, 1, 2, 3, 4 };
foo(&arr);
return 0;
}
コードは、互換性のない型が関数に渡されているという診断を生成します。たとえば、GCC は次のように文句を言います。
prog.c: In function 'main':
prog.c:9: warning: passing argument 1 of 'testFunction' from incompatible pointer type
コンパイラによって発行されるすべての診断に注意を払い、それらを理解していることを確認し、それらに対処するための適切な手段を講じる必要があります。この特定の場合、配列へのポインターを渡す場合は、そのようなものを受け入れるように関数を作成する必要があります。次に、ポインターを逆参照すると、配列が作成されます。したがって、同じようにアクセスします。
void testFunction(int (*test)[10]){
printf("%d", (*test)[1]);
}
は[]
よりも優先順位が高い*
ため、関数のパラメーター引数と の値にアクセスする場合の両方に括弧が必要ですprintf()
。へのポインタが参照されるint[10]
と、結果の値は でtest
定義された配列の最初の要素のアドレスになりますmain
。次に、[]
操作は配列の 2 番目の要素にアクセスし、期待した値を取得します。
int **test
以下のアサーションが常に真であることに注意すれば、配列へのポインターに対する の使用が間違っていると確信するかもしれません。
int test[10];
assert(&test == (void *)test);
コンパイラの警告が示すように、へのポインターへのポインターは、へのポインターとint
同じではありませんint[10]
。参照先の型によって、逆参照の結果の型が決まります。
そう:
int test[10] = { [1] = 5 };
testFunction(&test);
これは のアドレスをtest
に渡しますtestFunction
。変数のアドレスは、メモリ内の位置に対応します。これは配列の場合もそれほど違いはありませんが、配列変数のメモリ内の場所は最初の要素のアドレスです。したがって、上記で返されるアドレスは、単独で&test
返されるアドレスと同じです。test
このポインター値を へのポインターへのポインターとして扱うと、これは悲惨な結果をもたらしint
ますtestFunction
。まず、適切な演算子の優先順位を無視することに注意してください。したがって、最初の逆参照は次のようになります。
test[1]
test
へのポインターへのポインターとしてパラメーターを宣言するためint
、これによりアドレスがインクリメントtest
されsizeof(int *)
、結果が として扱われますint *
。次に、再度逆参照します。
*test[1]
これは、 の値test[1]
を取得し、 を取得しようとして再度逆参照するようになりましたint
。ただし、 によって返されるアドレスは、で定義されtest[1]
た配列と関係がなく、まったく無意味なメモリ位置にアクセスしています。test
main
int
パラメータ型へのポインタへのポインタの優先順位に注意を払っても、同様の問題が発生していました。
(*test)[1]
現在、ポインタへのポインタint[10]
は、ポインタへのポインタとして扱われ、int
最初に参照されます。これにより、 の配列の最初のsizeof(int **)
バイトがへのポインタとして扱われます。これはこの時点ですでに無意味な値ですが、配列の逆参照はこの値をバイト単位でインクリメントし、その値を逆参照して.test
main
int
sizeof(int)
int
他のユーザーは、通常はすでに行われている方法の例を示しましたが、 int ** を渡すことを主張する場合、演算子の優先順位により、構文は次のようになります。
void testFunction(int **test){
printf("%d", (*test)[1]);
}
int main()
{ int test[10];
test[1] = 5;
int *testptr= &test[0]; // or int *testptr= test;
testFunction(&testptr); // this passes an int **
return 0;
}
ただし、c では、配列の名前は配列要素へのポインターであるため、 int *ptrtest および ptrtest[1] がより一般的に使用されます。