
C言語で特に難しい挫折ポイントである「ポインタ」についてお話していきたいと思います。 ただ、その前にポインタと関係が深いハードウェアとOSの仕組みについて最低限をまとめておこうと思います。
ポインタはC言語で効率よく計算を行ったり、大きなサイズのデータを扱うための仕組みです。 ポインタのお話をする上で、どうしてもハードウェア(特にCPUやメモリ)、OSについての基本的な役割や動きを知っておくと理解しやすいかと思います。
プログラミングをしていく上で基本的なハードウェアの役割や仕組みを知ることは大切です。 それぞれのパーツがプログラムからどのように使われるのかを知っていることで、プログラムがどのように動作するのかをより理解することができると思います。 一般家庭用のコンピュータやゲーム機など、いろいろなマシンがありますが、基本的な構成は似ています。 コンピュータの基本的なパーツとして、CPU、メモリ、周辺機器(キーボードやマウス)、ディスプレイ、GPU(グラフィック専用の計算器)などがあります。 一番プログラミングする上で意識すべき、CPUとメモリから最低限知っておくとよい仕組みをお話しておきたいと思います。
CPUはマシンが演算(計算)を行うために必要となります。 CPUは Central Processing Unit の略で、中央演算処理装置と呼ばれます。 CPUにもいろいろな種類があり、Intel社が出しているPentium、Core iシリーズや、Acorn Computers社が出している 携帯ゲーム機やスマートフォンに多く採用されている、Arm シリーズのCPUなどあります。
こういったCPUでは命令を与えることで足し算や引き算などの簡単な演算を高速に行うことができます。 CPUへの命令はプログラムから出すことができます。 過去の内容でやってきたように、C言語などで書いてコンパイルしたプログラムを実行することで命令を与えてきていました。
CPUは基本的には計算した内容を大量に記憶(保存)しておくことができません。 レジスタと呼ばれる小さな記憶できる箇所に、計算するのに必要なパラメータ等を記録することができますが、 ゲームなどのマップデータや主人公のステータスなどをCPUのレジスタにすべて置いておくようなことはできないことになります。
このような大量のデータはメモリに記録しておきます。 メモリは基本的にマシンの電源を落とすまでは内容を記録することができます。 また、プログラムを実行するときのプログラムそのものもデータですので、一度ハードディスクやSDカードなどからメモリに読み込まれ、メモリの上で一つ一つプログラムの命令を読み取りCPUに命令を出しています。 このようにマシンがプログラムを動かしたりするときに主に使用されるメモリなので、日本語では主記憶装置とも呼ばれたりします。
主記憶装置とUSBメモリとは違うよ ここでいうメモリはUSBメモリなど、データをずっと保存しておけるもの(非揮発性メモリ)とは違うので注意してください。
2021年1月現在ではPCやスマフォのメモリとしては SDRAM と呼ばれるメモリの種類が非常に多く使われています。
CPUは演算、メモリはデータの記録保存ができるとお話しました。このメモリは高速で動作する代わりに、一度電気の供給が止まってしまうと記録している内容がすべて消えてしまいます。スマートフォンなどでもバッテリーがなくなったときに、保存していたなかった書きかけのメモなど、消えてしまったことがあるかもしれません。これらはメモリ上でデータを持っていたけど、電源の供給が止まってしまい、キレイにデータが飛んでしまったからです。
こういった電源の供給が止まったとき、データが消えてしまうようなメモリを揮発性メモリと呼びます。電気の流れを使って 0 と 1 (ビット)の情報を持っているため、このような欠点があります。
揮発性メモリのいろんな種類 実際にはこの揮発性メモリのデータの記録の方もいろいろな種類・方法があります。大量にデータ保存できること、素早く読み書きできること、安く生産できること、などの様々な点でスマホやゲーム機、PCに組み込むメモリの種類は選択されます。
スマホやゲーム用のSDRAM 主記憶装置に使われる SDRAM といっても、様々な種類、仕組みがあり、例えばスマホやゲーム機には使うのに電気の消費量が抑えられた LPDDR (Low Power DDR )というタイプの SDRAM が使われているようです。
電源が切れていてもデータが残っていてくれないと困りますね。ゲームでセーブ機能が存在しないようなものです。
例えばSDカード、USBメモリ、ハードディスク、SSD と呼ばれるものは一度記録したら、基本的には電源が切れても問題なく復旧できます。こういった装置は、磁気のS極・N極を利用したり、電子が保存されている位置などで 0 と 1 のビット情報を表現(NAND型フラッシュメモリ)することができます。0 と 1 が保存できれば良いので、初期は紙に穴が開いているか空いていないかでデータを保存する機械(パンチカード)など様々なものがあります。
ただし、こういったハードディスク、SSD などは補助記憶装置は主記憶装置と比べて保存も読み込みも低速となります。 ですので今すぐ計算するのに必要ないような画像データやプログラムなどを記憶しておき、いざ使うときには主記憶装置(メインメモリ)に読み込んでから使うのが基本となります。 また、一般的には補助記憶装置にはメモリよりも大きな容量を保存することができます。
このように主記憶装置を補助するような役割をもっているため、一般的に補助記憶装置と呼ばれています。
その他の主要な装置として、出力装置と入力装置があります。
出力装置はその名前の通り、画面やプリンタ、スピーカーなど、マシン(PCやスマホなど)の利用者に情報を渡すための装置です。
入力装置はマシンに対してなんらかの操作を伝えるための装置で、キーボードやマウス、スマホのタッチパネル、モーションセンサーやマイク(音声入力装置)なんかも含まれます。
最近では、VTuber 等キャラクタの動き(モーション)を入力するための機器である、Leap Motion 、VR機器、トラッキング機器も入力機器ですね。
OS は Operating System の略で、基本ソフトともいわれます。通常ゲームだったりWebブラウザなどのアプリを使うときは、この OS がアプリを管理しています。具体的には、複数のアプリに対して、どの程度の割合で CPU を使わせるか、アプリが止まったら強制終了させるかなどを管理しています。
アプリを作るプログラマーが直接意識することは少ないですが、プログラミングをするときも舞台裏で OS にはお世話になっています。 プログラムの中で出力装置や補助記憶装置などのハードウェアに直接アクセスするようなことは通常ありません。 基本的にはプログラムはOSが用意した命令を使って、ハードウェアにアクセスをしています。もし直接プログラムでハードウェアに命令を出すととても大変です。
今まで登場してきたC1言語の標準関数 いままでお話してきた printf 関数や scanf 関数についても内部で OS の用意した命令を利用しており、直接ハードウェアを操作しているわけではありません。
OSが用意した命令を使わなかったら非常に大変なプログラムを行う必要があります。 例えば、SDカードにセーブデータをファイルとして書き込むとき、SDカードにファイルを作る命令を理解しなければなりませんし、N社ハードディスクにファイルを書き込むときはN社ハードディスク専用の構造や命令を理解しなければなりません。 こういった面倒な処理をOSが代わりに引き受けてくれ、プログラマーはもっとシンプルに ”ファイルを〇〇のパスに書き込む” という命令をするだけでファイルを取り扱うことができます。
メモリについてもOSが管理してくれることで、直接プログラマはメモリのどの位置にデータを書き込むかなどを意識する必要がなくなります。
複数のプログラムをマシン上で動かすとき、OSはプログラムごとに専用のメモリの領域を割り当てたり、プログラムから別のプログラムへのメモリの書き込み、読み込みを防いだりしてくれています。 具体的には、プログラムを起動するとき、プロセスというプログラムが動作する領域をOSが作成し、プロセス同士で使うメモリの領域が被ったりしないように制御されています。 そのような便利な役割をOSが担当してくれるので、プログラマが作るプログラムでは、OSが割り当ててくれたプロセスのプログラム専用のメモリの領域だけを意識すれば良いことになります。
また、実際に物理的に存在するメモリのサイズを超えて、大きなサイズのメモリがプログラムが使えるように見せることができます。 このような機能は仮想メモリと呼ばれる仕組みを使っています。今後C言語でポインタを使うときにも、仮想メモリの機能にはお世話になります。
メモリや出力装置へのアクセスをするときなど、OSが用意した命令を通して機能を利用しますが、そのようなOSが用意した命令はシステムコールと呼びます。 C言語からもこのシステムコールを呼び出すことができます。 呼び出しかたは普通の専用の呼び出し方があるわけではなく、通常の関数と同じように利用することができます。
MacOS などの Unix系システムやMicrosoft の Windows系システム、AndroidなどのLinux系システムなどでシステムコールの呼び方は異なってきます。
ただ、システムコールを直接呼び出すことは少ないかもしれません。画面に文字を表示するときも write というシステムコールが使われていたりすますが、write システムコールを使う必要はなく、すでにお話しているように printf 関数など、より高機能な関数を利用すればよいからです。
今回お話したなかで、特に重要なポイントです。
この辺りをポインタを理解するうえで、なんとなく理解していると今後分かりやすいかと思います!
更新日 | 更新内容 |
---|---|
更新なし |
コメント、ありがとうございます。
ごめんなさい。エラーでうまく送信できませんでした。ご迷惑をおかけします。しばらくおいてから再度送信を試していただくか、以下から DM などでご連絡頂ければと思います。
Twitter:@NodachiSoft_jpお名前:以下の内容でコメントを送信します。よろしければ、「送信」を押してください。修正する場合は「戻る」を押してください
お名前: