ここでは、メモリとアドレスについてお伝えします。
今回説明する内容は、ざっくりとしたメモリの理解です。
また、この記事はコンピューターが動く仕組みという記事の続きです。
メモリをざっくりと理解する
まず、メモリをイメージで捉えていきましょう。
こちらの画像をご覧下さい。
これがメモリのイメージです。中央の青い長方形に情報(データ、命令、参照)が入っています。
番地の数はメモリの容量によって変わってきますが、例えば、4GBのメモリであれば、約40億の番地があります。
このイメージを元に、メモリの特徴を押さえていきましょう。
メモリには番地があり、CPUは全ての番地を参照できる。
上記の通り、メモリには番地があります。
先程のメモリの図の左側に0から振られた番号があるかと思いますが、これが番地です。
番地は、CPUがメモリからデータを引っ張ってくる時に使われます。
言い換えると、番地がなければCPUはメモリからデータを引っ張ってくることはできないのです。
メモリにはデータと命令が入っている
コンピューターの仕組みという記事で、CPUとメモリは計算ドリルをイメージすると分かりやすいと説明しました。
計算ドリルにかかれている問題を、CPUが順番に読み取り、回答を一つずつメモリに書き込んでいくというイメージです。
ここで、計算ドリルにかかれている情報というのは、大きく2つの種類があることを意識しましょう。
その2つとは、データと命令です。
例えば、1 + 2という問題があった場合、1と2がデータ、+が命令です。
実際のメモリにも、データと命令が書き込まれます。
CPUには、実際には非常に多くの命令の種類があり、様々な命令を使って複雑な処理を実現しているのです。
実際にどのようにデータと命令が書き込まれるのかという具体例は後ほどご紹介します。
メモリには、上から順番にデータが入っているとは限らない
Pythonプログラムがメモリにデータを入れていく時、上から順番にデータを入れていくと効率的なイメージがありますが、実際はそうではありません。
では、データが上から順番に入っているとは限らない中で、CPUはどうやってデータを操作するのでしょうか。
その秘密は、メモリにあります。
先程は、メモリには命令とデータが格納されているとお伝えしましたが、メモリには、更に番地の情報を入れることができるのです。
メモリには、参照情報も入れることができる(データを使い回すことができる)
これが非常に大切なポイントです。
メモリには、番地の情報を入れることができます。
具体例としては、2番地に入っているデータが(11番地)という番地を示している場合があるということです。
といっても、これだけではイメージが湧きづらいと思いますので、実際にPythonのコードを書き、それがどのような形でメモリに格納されているのかを見てみましょう。
なお、今回紹介する内容は、メモリを理解するため、実際にメモリに書き込まれる情報とは異なることをご理解下さい。
ここから、具体的なコードを使ってメモリの理解を深めていきますが、簡単にプログラムの仕組みを復習しましょう。
Pythonプログラムは、コードをCPUが理解できる内容に書き換える
コンピューターの仕組みを理解するという項目でお伝えしましたが、コンピューター上のプログラムというのは、人間とコンピューターの橋渡しのような役割をしています。
つまり、コードがメモリに格納される時には、Pythonプログラムがその橋渡しをしているのです。
ここからは、具体的にどういった形で橋渡しをしているのかという所から、メモリへのデータの格納方法について見ていきましょう。
このようなコードを考えてみましょう。
コードa = 1
b = a + 1
このコードを正確に理解するためには、変数・データ・代入という考え方を理解する必要があります。
このコードで、Pythonがメモリにどのようにデータを入れているのか、見ていきます。
まずは1行目です。1行目では、a = 1というコードがありますが、Pythonプログラムは、メモリ上の適当な番地に1というデータを入れます。
(実際のPythonプログラムはこのような動きはしません。メモリの理解を深めるため、分かりやすい記載にしています。)
そして、1というデータが入っている番地とaという変数を結び付けます。
例えば、Pythonプログラムが、1000番地に1というデータを入れたとしましょう。
ポイントは次の行です。2行目は、b = a + 1というコードです。
Pythonは、まず右辺のa + 1というコードを解釈します。
人にとってaに代入されている1というデータは、実際にはメモリでは1000番地に格納されていますので、Pythonプログラムはa + 1を以下のようにメモリに格納していきます。
1000番地(変数a)に入っているデータをCPUに移しなさい。
2というデータをCPUに移しなさい。
上記の2つのデータを足しなさい。
これで、CPUが理解できる形でコードが書かれました。
なぜデータをCPUに移すのかというと、演算はCPUでしかできないからです。詳しくは、コンピューターが動く仕組みという記事を参考にして下さい。
次に左辺を見ていきましょう。
bはあくまでも人間が認識するために使っている文字です。ですので、Pythonはbという文字を番地に置き換えます。
今回は、Pythonが1200番地とbを関連付けたとしましょう。
そうすると、メモリにはこのような命令が書かれます。
CPUに入っている先程の計算結果を、1200番地に書き込みなさい。
結果として、メモリ上の1200番地に3というデータが書き込まれました。
a + 2というコードは、結果から見れば1 + 1なのですが、実際のメモリには変数aに対応する番地の情報(そこには1というデータが格納されている)と、2というデータが足されているということを意識しましょう。
参照という考え方を覚えることが、プログラミングにおいて非常に重要
具体的な例と共に、メモリにどういった形でデータが格納されていくのかという点についてお伝えしました。
ポイントは、メモリには番地の情報が入っている場合があるということです。
普段の生活や、数学では参照という考え方は出てきませんが、Pythonを始めとするプログラミングをしっかりと理解するためには、この参照という考え方を理解することが非常に重要です。
参照が分かると何が良いのか
では、参照という考え方を理解すると、何が良いのでしょうか。
この答えは「プログラミングに対する理解が深まる」です。
簡単な例をご紹介します。
例えば、このようなコードがあったとしましょう
a = 1
a = 2
数学の世界では、このような式はあり得ないですよね。aは1か2かどちらなのか、という話になってしまいます。
ただし、今までの考え方で見ると、このコードは間違っていないということが分かります。
実際に、このコードを実行してみた時に、Pythonがどのように理解するのか、順番に見ていきましょう。
まず、a = 1というコードは先程の例と同じですよね。1というデータをメモリ上の番地に格納し、その番地とaという変数を関連づけて覚えておくのです。
ここで、1というデータが入っている番地を100番地としましょう。
次に、a = 2というコードです。このコードもa = 1とほとんど同じです。
2というデータをメモリ上の番地に格納し、その番地とbという変数を紐づけておくのです。
ここで、2というデータがはいっている番地を105番地としましょう。
すると、Pythonは混乱します。aという変数は、100番地と105番地のどちらを示しているのだろうか?という形です。
結論としては変数は書き換えられますので、この場合、Pythonはaという変数と105番地のデータを紐付けるのです。
例えば、次にa * 2というコードがあれば、Pythonは105番地のデータを2倍しなさい、という命令をメモリに書き込むのです。
具体例と共に、メモリとプログラムの関係についてお伝えしました。
プログラミングを理解するためには、参照という考え方を理解することが非常に重要です。
番地を参照するということが理解できれば、プログラミングに対する理解もぐっと深まるでしょう。
メモリとアドレスのまとめ
(1) メモリには、データ・命令・番地のいずれかの情報が入っている
(2) a=1、1=2が成立するのは、aの参照先が上書きされるから
メモリとアドレスについて学んだあとは
Pythonについて勉強をはじめていきましょう。まずはデータと代入について理解していきましょう。