C のポインターと配列の宣言の基本について混乱しています。次の 2 つのステートメントの違いを知りたいのですが、2 番目のステートメントで配列へのベース アドレスが ptr に割り当てられる点が異なります。
int a[2][3]= { (1,2,3),(4,5,6)};
int (*ptr)[3] = &a[0];
明確にするために例を引用してください。2行目のR側の[3]はどのような効果がありますか?
1. 二次元配列:
int a[2][3]= { {1,2,3},{4,5,6}};
このステートメントをメモリ内に置くと、2x3 の整数がすべてメモリ内で隣接しています。それらにアクセスする方法を知っていると思いますが、そうでない場合は明確にします。
a[0][0] : 1
a[0][1] : 2
a[0][2] : 3
a[1][0] : 4
a[1][1] : 5
a[1][2] : 6
2. 配列へのポインタ:
int (*ptr)[3] = &a[0];
ptr はメモリの int[3] ブロックを指します。したがって、int[3] タイプにのみ割り当てることができます。
ptr= &a[0];
ptr= &a[1];
違いは、このポインターには独自のメモリがなく、int[3] 変数に割り当てるか、割り当てる必要があることです。
ptr= malloc (2*sizeof(int[3]);
このようにして、ptr を次のように初期化すると、ptr が指すメモリを使用できます。
for(int j=0; j<2; j++)
for(int i=0; i<3;i++)
ptr[j][i]=i+j*3+1;
この場合、int a[2][3] と同じメモリ表現になりますが、このメモリはスタックではなくヒープにあります。いつでもメモリの再割り当て/解放を選択でき、このメモリは削除されません。関数が終了したら。
Cの演算子の優先順位の規則を知っておく必要があります:http://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B#Operator_precedencehttp://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B#Operator_precedence
int (*ptr)[3]
とは対照的にint * ptr [3]
int (*(ptr [3]))
1つ目はサイズ3のintの配列へのポインター(*は変数名に近いことに注意)です。2つ目はintポインターのサイズ3の配列に等しいです。
式の解釈方法に疑問がある場合は、次のサイト(http://cdecl.org/ )を使用することもできます。
a は、行サイズ 2、列サイズ 3 の 2 次元配列です。
一方、サイズが 3ptr
の配列へのポインターint
しかし、あなたの配列のa
初期化は正しい方法ではありません
soを使用()
したので、コンマ演算子が有効になり、3
andで初期化され6
、配列の他の要素が実際の初期化の使用を行うa
ことになります0
{}
&a[0] は、配列の最初の要素のアドレスです (a に対しても同じ値を出力することを意味します)。
ただし、これ&a[0]
は、ポインター算術演算を実行すると有効になりますptr
配列の場合、次の 3 つの点に注意してください。
--->int *ptr=&a[0][0];
最初の要素のアドレスから次の要素ptr++
が得られますa[0][1]
---> &a[0] = 最初の要素のアドレスですがint (*ptr)[3]=&a[0]
、そうすると、ptr++
ポインターは行全体のサイズだけ増加し、ptr は次の行を直接指すようになり、ptr が指すようになります&a[1]
---> &a = 配列全体のアドレスであり、それを保持して実行するint (*ptr)[2][3] =&a
と、ptr++
ポインターは配列全体のサイズだけ増加します。