注&arr
は完全な3次元文字配列のアドレスですが、arr
は2次元文字配列の最初の要素を指します。図中の以下のようなもの:char(*)[5][7][6]
ある
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
の寸法[5][7][6]
のチャー3次元アレイのアドレスです。 &arr
と&arr + 1
の間の値の差は、5 * 7 * 6 * sizeof(char)
= 210
です。
char[5][7][6]
のサイズは5 * 7 * 6 * sizeof(char)
です。
コードで&arr
は3次元配列を指し、&arry + 1
次の3次元配列(私たちのコードには存在しません)を指します。
チェック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);
あなたは、プレーン(char*)
にタイプchar(*)[5][7][6]
のアドレスを型キャスト、およびsizeof char[5][7][6]
は210
両方のアドレスがはるかに210あるからです。 (sizeof(char) == 1
を覚えておいてください)。これが理由です。210
最初のステートメントで述べたように、arr
は、2次元の文字配列である最初の要素のアドレスです。タイプarr
はchar(*)[7][6]
です。現在、1つの要素(2次元配列のサイズは6 * 7 * sizeof(char) = 42
)です。
(注:3次元配列は、各要素が2次元配列である1次元配列と考えることができます)。あなたの第三の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*)?を読む必要があります。この変換は完全には定義されていません。 (私の説明はあなたの出力と私が与えた出力です)。作業コードの下に、さらに明確化のチェックのために
codepade:
int main()
{
char arr[5][7][6];
printf(" arr : %p\n", arr);
printf(" arr+1: %p", arr + 1);
return 0;
}
で出力は次のようになります。(arr + 1) - (arr)
= 0xbf4836a8
間
arr : 0xbf48367e
arr+1: 0xbf4836a8
テイク差 - 0xbf48367e
= 0x2a
= 42
。
最終のprintf:p
3-Dの文字列(= &arr
)へのポインタであるため
printf("%d\n", (unsigned)(p + 1) - (unsigned)p);
ジャスト(第2のprintfに類似)&arr+1
と&arr
= 210
間の差を取ります。そしてあなたは値型(ポインタ型ではない)に型キャストしています。
はさらに、が(ただ、目的を理解するための追加、私は読者がそれが役に立つでしょう推測)、
は私達があなたのより深い概念を理解するのに役立ちますsizeof演算子を使用してarr
と&arr
の間に1つの以上の違いを学ぶことができます。この最初の読み取りのために:sizeof
Operator
あなたは配列識別子に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
= (arr + 0)
。現在、*
を使用しています。(arr + 0)
の参照演算子は、アドレスに値を与えます。
- お知らせ
sizeof(arr[0])
は= 7 * 6 * sizeof(char)
42
を与えます。そして、この証明は概念的には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
ヒント: '= 42' 6 * 7、' 5 * 7 * 6 = 210' –
@Arminができますあなたが説明してください? – Alex
もう1つのヒント - アドレスが最終的なタイプではなく元のタイプであると仮定してポインタの算術演算を*行った後で*別のタイプに変換していない場合... – twalberg