memory |address:value| (value of X means unknown):
|0:X|1:X|2:X| ... |5:X| .. |12:1| ... |255:X|
ステップ3:あなたは、ポインタ
を割り当てる リコールステップ2 ...セルp
は、x
へのポインタを格納します。
memory |address:value| (value of X means unknown):
|0:X|1:X|2:X| ... |5:12| .. |12:1| ... |255:X|
ステップ4:あなたが第2のポインタを
program:
int x = 1;
int *p;
p = &x;
int *p2;
...
リコールを宣言している 我々はしたがって12 p
(セル5)に格納され、セル12はx
に割り当てられている知っていますステップ3 ...そして、あなたのコンパイラは、(値がX
あるので、それはまだ割り当てられていないのです)変数p2
ためのメモリセル6を割り当てた:
memory |address:value| (value of X means unknown):
|0:X|1:X|2:X| ... |5:12|6:X| .. |12:1| ... |255:X|
ステップ5:(!まだ未定義の)あなたは第二を割り当てる を指示先:
program:
int x = 1;
int *p;
p = &x;
int *p2;
*p2 = *p;
...
リコールステップ4、次いで*p
はp
そうセル5であることをコンパイラリコールを行います実際の結果のアドレスとしてその値を使用します。セル12
からの読み出しは、1を返します。コンパイラは、セル#6にp2
という名前が与えられていることを知っています。p2
は6です。 *p2
は、p2の値を読み取って実際のストレージのアドレスとして使用する必要があることを意味します。しかし、私たちの場合、この値はX
(未定義)です!しかし、実際のメモリチップには未定義の値はなく、ブート時に何かがそこに格納されています(例えば、値42
)。仮想メモリが影響を受ける場合、状況はさらに複雑になりますが、ここでそれについて議論したくありません。だから、ブート時に電荷と宇宙線が42
のランダムな値にこのセルを初期化したとしましょう。 *p2 = *p
が実行されるときに何が起こるかを見てみましょう:*p
が返された方法を見てきました。今、プログラムはそれをどこに保存するかを調べようとします。それは42を生成するp2
の値を読み込みます、今のプログラムは、メモリセル42
に1
を格納すると結果が表示されます:現実の世界で
memory |address:value| (value of X means unknown):
|0:X|1:X|2:X| ... |5:12|6:X| .. |12:1| ... |42:1| ... |255:X|
をしかし、頻繁にクラッシュにつながる初期化されていない値を使用して。仮想メモリが関与すると、いくつかの領域のアドレス空間(256個のアドレス)にはメモリセルが割り当てられず、そのようなアドレスに書き込むとクラッシュする可能性があります。
ステップ6:あなたが第2のポインタを割り当て、それがx
に再び指して定義させるされている :
program:
int x = 1;
int *p;
p = &x;
int *p2;
p2 = p;
...
リコールステップ4と、プログラムがクラッシュの原因となったステップ5を無視し...コンパイラは、どのセルがp
(セル5)とp2
(セル6)の両方に使用されているかを知っています。したがって、割り当てp2=p
はこのように動作します。p
(12)から値を取ってポインタとして解釈せず、代わりにp2
にコピーしてください。今すぐp2
はx
(セル12)へのポインタで初期化されます。
memory |address:value| (value of X means unknown):
|0:X|1:X|2:X| ... |5:12|6:12| .. |12:1| ... |42:X| ... |255:X|
ステップ7:
program:
int x = 1;
int *p;
p = &x;
int *p2;
p2 = (int*)100;
...
...のは、この行に焦点を当ててみましょう:p2 = (int*)100;
これは無名のを指すようにポインタを割り当てる方法を示しますが、名前の場所へのポインタを代入している メモリセル。コンパイラがまだセル#100に名前を割り当てていないことを思い出してください。しかし、この記憶場所に興味深いものがあることが分かっている場合、例えばコンピュータ装置がそのセルを介して私たちと通信している場合などはどうでしょうか?キーボードがメモリセル#100に次の文字を格納していて、それを読んでみたいとしたら?今、あなたは*p2
としてそれを読むことができます:
memory |address:value| (value of X means unknown):
|0:X|1:X|2:X| ... |5:12|6:100| .. |12:1| ... |42:X| ... |100:keyboard| ... |255:X|
ステップ8:あなたは配列へのポインタの関係を明らかしている :
program:
int x = 1;
int *p;
p = &x;
int a[5];
a[2]=18;
int *p2 = a;
p2[2]=3;
...
を...のは、この行に焦点を当ててみましょう:int a[5];
:この宣言行は5つのセルを割り当てるようにコンパイラに指示し、そのセルにはa
という名前を使用します。そして、コンパイラ細胞7、8、9、10、a
のための11に割り当てられた:それはポインタ割り当てなかったこと
memory |address:value| (value of X means unknown):
|0:X|1:X|2:X| ... |5:12|6:100|7:X|8:X|9:X|10:X|11:X|12:1| ... |42:X| ... |100:keyboard| ... |255:X|
をノート - a
は文字通り、他の変数のように使用されるでしょう!これはa[2]=18
の仕組みです:最初のコンパイラはが開始され、7
ということを知っていますので、その値を最初に使用してから2
を追加して9
を追加します。だから、ターゲットストレージセルが発見された - それは、細胞数9ですので、そのセルに18を格納します。
|0:X|1:X|2:X| ... |5:12|6:100|7:X|8:X|9:18|10:X|11:X|12:1| ... |42:X| ... |100:keyboard| ... |255:X|
それでは、どのようにint *p2 = a;
作品を見てみましょう:コンパイラはこのため7時a
開始7に格納されていることを知っていますp2
もしアレイp2[2]=3;
として使用することができ、ポインタを初期化した後
|0:X|1:X|2:X| ... |5:12|6:7|7:X|8:X|9:18|10:X|11:X|12:1| ... |42:X| ... |100:keyboard| ... |255:X|
(セル#6は、ステップ4でp2
に割り当てられているリコール):これは*(p2 + 2) = 3
の略です。 p2
の値は7で、2を追加して9を与えるので、私たちは、セル#9に3を格納している:
|0:X|1:X|2:X| ... |5:12|6:7|7:X|8:X|9:3|10:X|11:X|12:1| ... |42:X| ... |100:keyboard| ... |255:X|
iの値、変数、ポインタと配列の関係をカバーしようとしたような長い説明のために申し訳ありませんと最もこれらのユースケース
私はいくつかの段落でこのような質問に答えることはできないと思います。プログラミング、C言語、オペレーティングシステム、コンピュータアーキテクチャ、命令セットなどについての書籍を読むことに何週間も費やしてください。 –
'int * p = x;'は動作しません。 'int * p =&x;'でなければなりません。一般的なルール - 左のものの "タイプ"は、右のものの "タイプ"と同じでなければなりません。これはポインタを含むものだけでなく、すべての代入と初期化に適用されます。 – fukanchik
'int * p;'は整数へのポインタです。つまり、 'p'は整数のアドレス*を保持します。 'int * p = x;'を実行すると、 'x'の値を整数の*アドレス*に代入します。これは有効ではない可能性があります(' x'の値が1の場合、整数のアドレスは1で、おそらく有効ではありません)。これは 'int * p =&x;'でなければなりません。これは 'p'の値を変数' x'のアドレス*に割り当てることを意味します。 – lurker