2 次元の char 配列である最初の要素を指して&arrいるのに対し、完全な 3 次元の char 配列のアドレスであることに注意してください。arr以下の図のようなもの:
0xbf8ce2c6
+------------------+ ◄-- arr = 0xbf8ce2c6
| 0xbf8ce2f0 |
| +------------------+ ◄-- arr + 1 = 0xbf8ce2f0
| | 0xbf8ce31a | |
| | +------------------+ ◄-- arr + 2 = 0xbf8ce31a
| | 0xbf8ce344 | | |
| | | +------------------+ ◄-- arr + 3 = 0xbf8ce344
| | 0xbf8ce36e | | | |
| | | | +------------------+ ◄-- arr + 4 = 0xbf8ce36e
| | | | | | | | | |
+---|---|---|--|---+ | | | | Each are 7*6, 2-Dimensional
| | | | | | | | Consists Of 42 bytes
+---|---|--|-------+ | | |
| | | | | |
+---|--|-----------+ | |
| | | |
+--|---------------+ |
| |
+------------------+
The diagram show:
1. How a 3-dimensional can be interpreted as series of 2-dimensional arrays
2. Here (arr + i) points to a 2-D array
3. Notice difference between: (arr + i + 1) - (arr + i) = 0x2a = 42, where i = [0, 4]
の型は&arr、char(*)[5][7][6]次元 の char 3D 配列のアドレスです[5][7][6]。&arrとの値の違い&arr + 1は5 * 7 * 6 * sizeof(char)=210です。
のサイズですchar[5][7][6]ので5 * 7 * 6 * sizeof(char)。
コードでは、3 次元配列と次の 3 次元配列 (コードには存在しません) を&arr指しています。&arry + 1
codepadeでこの作業コードを確認してください:
int main()
{
char arr[5][7][6];
printf(" &arr : %p", &arr);
printf(" &arr+1: %p", &arr + 1);
return 0;
}
出力:
&arr : 0xbf5dd7de
&arr+1: 0xbf5dd8b0
(&arr + 1) - (&arr)= 0xbf5dd8b0 - 0xbf5dd7de= 0xd2=の違い210。
2 番目の printf で:
printf("%d\n", (char *)(&arr + 1) - (char *)&arr);
type のアドレスchar(*)[5][7][6]を plain(char*)に型キャストします。sizeofchar[5][7][6]は210両方とも 210 far であるためです。(覚えておいてsizeof(char) == 1ください)。これが出力の理由です。210
最初のステートメントで述べたようにarr、文字の 2 次元配列である最初の要素のアドレスです。のタイプはarrですchar(*)[7][6]。これで 1 つの要素 (サイズの 2 次元配列は6 * 7 * sizeof(char) = 42) になります。
(注: 3 次元配列は、各要素が 2 次元配列である 1 次元配列と考えることができます)。
3 番目の printf で:
printf("%d\n", (unsigned)(arr + 1) - (unsigned)arr);
符号なしの値に型キャストします (ただし、アドレス/ポインター型には型キャストしません)。arr + 1との違いarrは42 * sizeof(char)= 42(つまり のサイズに等しいchar[7][6]) です。したがって、printf ステートメントの出力は次のとおり42です。
注: sizeof (int) == sizeof (void*)? を読む必要があります。、アドレスを値に型キャストしているためです。この変換は完全には定義されていません。(私の説明は、あなたの出力と私が与えた出力についてです)。
さらに明確にするために、コードパッドの作業コードの下を確認してください。
int main()
{
char arr[5][7][6];
printf(" arr : %p\n", arr);
printf(" arr+1: %p", arr + 1);
return 0;
}
出力は次のとおりです。
arr : 0xbf48367e
arr+1: 0xbf4836a8
(arr + 1) - (arr)= 0xbf4836a8- 0xbf48367e= 0x2a=の差を取る42。
最後の印刷:
printf("%d\n", (unsigned)(p + 1) - (unsigned)p);
&arr+1と&arr=の差を取るだけです ( 2102 番目の printf と同様)。そして、それを値型(ポインター型ではなく)に型キャストしています。p&arr
さらに、(目的を理解するために追加するだけで、読者が役立つと思います)、
概念をより深く理解するのに役立つ sizeof 演算子の使用arrとの違いをもう 1 つ学びましょう。&arrこの最初の読み取り:sizeofオペレーター
演算子を配列識別子に適用するsizeofと、結果は、配列識別子によって表されるポインターのサイズではなく、配列全体のサイズになります。
codepadeでこの作業コードを確認してください:
int main()
{
char arr[5][7][6];
printf(" Sizeof(&arr) : %lu and value &arr: %p\n", sizeof(&arr), &arr);
printf(" Sizeof(arr) : %lu and value arr : %p\n", sizeof(arr), arr);
printf(" Sizeof(arr[0]): %lu and value a[0]: %p\n",sizeof(arr[0]), arr[0]);
return 0;
}
その出力:
Sizeof(&arr) : 4 and value &arr: 0xbf4d9eda
Sizeof(arr) : 210 and value arr : 0xbf4d9eda
Sizeof(arr[0]): 42 and value a[0]: 0xbf4d9eda
私の図に示したようにarr、2 次元配列である最初の要素を指しています。だからarr= (arr + 0)。現在、*逆参照演算子 atを使用(arr + 0)すると、アドレス so で値が得られます*(arr + 0) = arr[0]。
- 注意
sizeof(arr[0])は 42=を与え7 * 6 * sizeof(char)ます。そしてこれは、3 次元配列が 2 次元配列の配列であることを概念的に証明しています。
上記の私の回答では、「サイズchar[5][7][6]は5 * 7 * 6 * sizeof(char)です」のように何度も書いたからです。だから私は @ codepadeの下に興味深いコードを追加しています:
int main(){
printf(" Char : %lu \n", sizeof(char));
printf(" Char[5] : %lu \n", sizeof(char[6]));
printf(" Char[5][7] : %lu \n", sizeof(char[7][6]));
printf(" Char[5][7][6]: %lu \n", sizeof(char[5][7][6]));
return 1;
}
出力:
Char : 1
Char[5] : 6
Char[5][7] : 42
Char[5][7][6]: 210