実際の動作は次のとおりです。コードとコメントを参照してください。
#include <stdio.h>
int x[3][5] =
{
{ 1, 2, 3, 4, 5 },
{ 6, 7, 8, 9, 10 },
{ 11, 12, 13, 14, 15 }
};
int (*pArr35)[3][5] = &x;
// &x is a pointer to an array of 3 arrays of 5 ints.
int (*pArr5a)[5] = x;
// x decays from an array of arrays of 5 ints to
// a pointer to an array of 5 ints,
// x is a pointer to an array of 5 ints.
int (*pArr5b)[5] = &x[0];
// &x[0] is a pointer to 0th element of x,
// x[0] is an array of 5 ints,
// &x[0] is a pointer to an array of 5 ints.
int *pInta = x[0];
// x[0] is 0th element of x,
// x[0] is an array of 5 ints,
// x[0] decays from an array of 5 ints to
// a pointer to an int.
int *pIntb = *x;
// x decays from an array of arrays of 5 ints to
// a pointer to an array of 5 ints,
// x is a pointer to an array of 5 ints,
// *x is an array of 5 ints,
// *x decays from an array of 5 ints to
// a pointer to an int.
int *pIntc = &x[0][0];
// x[0][0] is 0th element of x[0],
// where x[0] is an array of 5 ints,
// x[0][0] is an int,
// &x[0][0] is a pointer to an int.
int main(void)
{
printf("&x=%p x=%p &x[0]=%p x[0]=%p *x=%p &x[0][0]=%p\n",
pArr35, pArr5a, pArr5b, pInta, pIntb, pIntc);
return 0;
}
出力例:
&x=0040805c x=0040805c &x[0]=0040805c x[0]=0040805c *x=0040805c &x[0][0]=0040805c
明示的または暗黙的に 0 のインデックスを使用し、配列が連続しており、配列の最初 (IOW、0 番目) の要素が常に配列の最小アドレスにあるため、結果のポインターはすべて同じ値になります。したがって、3 つの異なるポインター型がありますが、すべて実質的に x[0][0]、つまり 1 に等しい要素を指します。
この配列のポインターへの減衰は、C および C++ の非常に重要な機能ですが、すぐに把握するのは困難です。
配列にポインターを渡すときに、よりコンパクトなコードを記述できます。最初の要素のアドレスを取得する代わりに、配列の名前を記述するだけです。
char str1[] = { 's', 't', 'r', '1', '\0' };
char str2[] = "str2";
printf("%s %s %s %s\n", &str1[0], str1, &str2[0], str2);
出力:
str1 str1 str2 str2
また、クレイジーなこともできます。
int y[3] = { 10, 20, 30 };
printf("%d %d %d %d\n", y[2], *(y+2), *(2+y), 2[y]);
出力:
30 30 30 30
すべては、配列とポインタに関してa[b]
は同等だからです。*(a+b)