重複の可能性:
2 次元配列はメモリ内でどのようにフォーマットされますか?
int map[3][3] = {1,2,3,4,5,6,7,8,9};
int **p = map;
printf( "%d", *p+1 );
結果が5である理由を誰か教えてもらえますか? で、もし
printf( "%d", *p+2);
結果は9 ? (Visual C++ でコンパイル)
重複の可能性:
2 次元配列はメモリ内でどのようにフォーマットされますか?
int map[3][3] = {1,2,3,4,5,6,7,8,9};
int **p = map;
printf( "%d", *p+1 );
結果が5である理由を誰か教えてもらえますか? で、もし
printf( "%d", *p+2);
結果は9 ? (Visual C++ でコンパイル)
H2C03の答えを修正するには...
最初の逆参照により、配列 1 の次元に移動します。具体的には、「1」のエントリを指さしたままにします。
ここにいるほとんどの人が完全には理解していないように見えるのは、次に何が起こるかです. この時点で、' p' はまだポインターと見なされます。アドレス「1」が含まれていると考えられます。「+1」を実行すると、実際にポインター演算が行われます。sizeof(int ) は (通常) 4 であるため、単純に行列の最初の要素 +4 を出力しています。したがって、+2 は +8 に変換されます。これは、ポインターの算術演算は常に、ポインターが指す「もの」のサイズに関して行われるためです。したがって、5 と 9 が得られます。
コードの簡単なディスアスムが表示されます。
mov eax, DWORD PTR ?p@@3PAPAHA ; p
mov ecx, DWORD PTR [eax] ; deref of p (which is '1')
add ecx, 4 ; let's just +4 it and push it as the arg to printf
push ecx
push OFFSET $SG3670
call _printf
配列はポインターではないためです。配列はメモリ内で連続しているため、二重ポインターは 2 次元配列と同等ではありません。配列が作成され、次のようにデータが入力されます。
map[0][0] = 1
map[0][1] = 2
map[0][2] = 3
map[1][0] = 4
map[1][1] = 5
map[1][2] = 6
map[2][0] = 7
map[2][1] = 8
map[2][2] = 9
これを double ポインターに割り当てると、いくつか間違ったことをしています。例えば:
printf("%d", *p + 1);
あなたが思っていることをしません。の型は*p
is ですint *
が、%d
フォーマット指定子はint
. 基本的に、配列は同じではないため、ポインターと同じように扱わないでください。このような状況を正しく処理する方法を理解するために、C FAQ の関連部分をお読みください。基本的に、この場合は 1 次元ポインターを使用して適切にインデックスを付けるだけで十分です。
デモンストレーション: