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
=の差を取るだけです ( 210
2 番目の 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