私は、多くの場合、配列の名前がメモリ
のブロックに一定のポインタであることを聞いてあなたはしばしば誤解してきた - またはあなたが単に誤解しました。配列は、メモリブロックへの定数ポインタではありません。配列は、一連のサブオブジェクトを含むオブジェクトです。すべてのオブジェクトはメモリのブロックです。ポインタは、オブジェクトのアドレスを含むオブジェクトであり、オブジェクトを指しています。
したがって、a
は配列で、p
はa
の最初のサブオブジェクトを指しています。
int a[10];
と
int * const p= a;
は、配列[]は、また、指すように変更されなくてもよいように、pは、メモリの同じブロックを指すポインタであるという意味で等しくなければなりません。メモリ内の別の場所。
それは同じのあなたの定義である場合には非配列が同様のオブジェクトに対して、それが成り立つ:
char c;
int * const p = &c;
ここp
「c
と同じメモリへのポイント」とポイントに変更することはできませんメモリ内の別の場所に移動します。これは、char
オブジェクトがポインタと「等しい」ことを意味しますか?いいえ、配列はどちらでもありません。
ただし、配列の同じ要素を指す定数ポインタ(配列の名前)ではありませんか?
いいえ、配列の名前は定数ポインタではありません。 char
の名前のように、定数ポインタではありません。
配列の名前は、配列の最初の要素のアドレスを保持します。
もっと一般的に言えば、配列に固有のものではありません。変数の名前は、その変数名が持つオブジェクトの「アドレスを保持する」。アドレスは実行時にメモリに保持されません。これはコンパイル時にコンパイラによって保持されます。変数を操作するとき、コンパイラはオブジェクトが正しいアドレスにあることをコンパイラで確認します。
アレイのアドレスは常に、アレイの最初の要素(サブオブジェクト)があるアドレスと同じです。したがって、実際にはその名前は - 少なくとも概念的には - の同じアドレスを保持します。
*(a+1)
を使用している場合、これはa[1]
と同じですか? [タイプミス]
右。私は詳しく説明します:一つは、ポインタの場合に別の方法を書くことです。ああ、しかしa
はポインタではありません! catchは次のとおりです。配列オペランドは暗黙的に最初の要素へのポインタに変換されます。この暗黙の変換は、減衰と呼ばれます。これは配列型の特殊な機能です。ポインタと配列の違いを理解するのが難しい特殊な機能です。
したがって、配列の名前はポインタではなくても、ポインタに崩壊する可能性があります。特定のコンテキストでのみ、名前が常にポインタに崩壊するとは限りません。 operator[]
を使用すると減衰し、operator+
を使用すると減衰します。サブオブジェクトの型へのポインタを受け入れる関数に配列を渡すと、減衰します。 sizeof
を使用すると減衰しません。参照によって配列を受け入れる関数に渡すと減衰しません。
あなたはしばしば誤解を招いたことがあります。または単に誤解したことがあります。配列はポインタではありません。 – user2079303
タイプ「T」およびサイズ「N」の配列は、シーケンシャルメモリに配置された「N」個の「T」型オブジェクトです。ポインタがそのメモリを指すようにできるだけで、配列をポインタにすることはできません。 – DeiDei
C++は強く型付けされた言語であり、特にsizeofは型を参照するため、これらは異なっています。 aとpが交互に使用できるランタイムケースがたくさんあります(正しい範囲内にある限り)が、それらはまだ異なるタイプです。 –