他の答えは正しいですが、3つすべてに同じ値が含まれる可能性があるという考えを強調するものはありません。そのため、それらは何らかの形で不完全です。
他の回答からこれが理解できない理由は、すべてのイラストが、ほとんどの状況で有用かつ間違いなく合理的である一方で、ポインターx
がそれ自体を指す状況をカバーできないためです。
これはかなり簡単に構築できますが、明らかに理解するのが少し難しいです。以下のプログラムでは、3つの値をすべて同一にする方法を示します。
注:このプログラムの動作は定義されていませんが、ここでは、ポインタができることの興味深いデモとして純粋にここに投稿していますが、すべきではありません。
#include <stdio.h>
int main () {
int *(*x)[5];
x = (int *(*)[5]) &x;
printf("%p\n", x[0]);
printf("%p\n", x[0][0]);
printf("%p\n", x[0][0][0]);
}
これはC89とC99の両方で警告なしにコンパイルされ、出力は次のようになります。
$ ./ptrs
0xbfd9198c
0xbfd9198c
0xbfd9198c
興味深いことに、3つの値はすべて同じです。しかし、これは驚くべきことではありません!まず、プログラムを分解してみましょう。
x
5つの要素の配列へのポインタとして宣言します。各要素はintへのポインタ型です。この宣言は、ランタイムスタックに4バイトを割り当てます(または、実装に応じてそれ以上。私のマシンのポインターは4バイトです)。したがってx
、実際のメモリの場所を参照しています。言語のCファミリでは、のコンテンツx
は単なるガベージであり、以前の場所の使用から残されたものであるため、それx
自体はどこにもポイントせず、割り当てられたスペースには間違いありません。
したがって、当然、変数のアドレスを取得しx
てどこかに置くことができるので、それがまさに私たちが行うことです。しかし、先に進み、それをx自体に入れます。の&x
タイプはとは異なるx
ため、警告を出さないようにキャストを行う必要があります。
メモリモデルは次のようになります。
0xbfd9198c
+------------+
| 0xbfd9198c |
+------------+
したがって、アドレスの4バイトのメモリブロックには0xbfd9198c
、16進値に対応するビットパターンが含まれています0xbfd9198c
。十分に単純です。
次に、3つの値を出力します。他の答えは、それぞれの表現が何を意味するかを説明しているので、関係は今明確になっているはずです。
値は同じであることがわかりますが、非常に低レベルの意味でのみ...ビットパターンは同じですが、各式に関連付けられた型データは、解釈された値が異なることを意味します。たとえばx[0][0][0]
、フォーマット文字列を使用して印刷した場合%d
、大きな負の数が得られるため、実際には「値」は異なりますが、ビットパターンは同じです。
これは実際には非常に単純です...図では、矢印は異なるメモリアドレスではなく同じメモリアドレスを指しています。ただし、予期しない結果を未定義の動作から強制することはできましたが、それだけです-未定義です。これは製品コードではなく、完全を期すための単なるデモンストレーションです。
妥当な状況では、を使用malloc
して5つのintポインターの配列を作成し、再びその配列でポイントされるintを作成します。malloc
常に一意のアドレスを返します(メモリが不足している場合を除き、その場合はNULLまたは0を返します)。そのため、このような自己参照ポインタについて心配する必要はありません。
うまくいけば、それがあなたが探している完全な答えです。あなたは期待すべきではありませんx[0]
、x[0][0]
とx[0][0][0]
等しくなるように、しかし、強制場合、彼らは可能性があります。何か問題があった場合は、お知らせください。わかりやすくします。
x[0]
、x[0][0]
およびx[0][0][0]
さまざまな種類があります。それらを比較することはできません。どういう意味!=
ですか?