コンピューターの基本構成は図1に示したとおりであるが、 制御装置と演算装置、記憶装置、入力装置、 出力装置を五大装置と呼ぶ。それぞれは、次のような働きがある。
これらのなかで、制御装置と演算装置をまとめて中央制御装置(CPU:Central Processing Unit)と言う。これを一つのチップにまとめたものを MPU(Micro Processing Unit) と言 うことになっている。ただ、MPUとCPUはほとんど同義語として使われるので、本講義では 全て CPU に統一する。その方が諸君もなじみ深いであろう。
プログラマーはメモリーの内容について、ある程度自由に変更ができる。そのようなこと から、メモリーを意識してプログラムを作成することが重要である。アセンブラー言語を使うと なるとCPUについても意識が必要であろうが、C言語ではそこまで要求しない。
本日のメインテーマはポインターであるが、それを深く理解するために、メモリーの知識 が必要である。しかし、そんなに難しいことではない。
メインメモリーの役目は、命令とデータからなるプログラムを記憶することである。そのプロ グラムは全て、0と1の数字で表せ、2進数で表現可能である。どのようなモデルでこの2進 数が格納されているか学習する。
プログラムという情報は記憶するだけでは全く役に立たない。記憶した内容を取り出せて 初めて、活用ができる。そこで、メモリーは記憶するための住所が決められている。この 住所のことをアドレス(address)と言い、0から整数の番地がふってある。諸君が使ってい るパソコンのアドレスは32ビットで表現されている3。そして、一つの番地には、8個の0と1が記憶 できる。この様子を図3に示す。
図を見て分かるとおり、2進数の表現は桁数が多くて人間にとって大変である4。そこで、通常は、2進数の4桁をまとめて、16進数で 表す。そうすると、アドレスは16進数8桁、記憶内容は16進数2桁で表すことができ、分か りやすくなる。その様子を図4に示す。
ついでに述べておくが、1個の0あるいは1の情報量を1ビットと言う。8ビットで1バイトと 言う。従って、メインメモリーの一つの番地(アドレス)には、1バイト(8ビット)の情報が 記憶できる。
メモリーについて覚えておくことは、以下の通りである。
それでは、実際にメモリーにデータが格納する様子を見よう。次のようにプログラムに書 いたとする。
double x=-7.696151733398438e-4; int i=55; char a='a';それぞれのデータは、
鋭い学生は、データの並びが逆であることが分かるであろう。例えば、整数のiであ
るが、
なので、
と並ぶと考えられるが、実際は図
5の通り逆である。これはCPUがそのように作られ
ているからである。このように逆に配置させる方法をリトルエンディアンと言
う。Intel社のCPUはリトルエンディアンである。一方、そのままのメモリーに配置する方
法はビッグエンディアンと呼ばれる。このようにメモリーにデータを並べる方
法は2通りあって、それをバイトオーダーと言う。
ここで、理解しておくべきことは、以下の通りである。
それでは、リスト1に示す簡単なプログラムで、データとメモリー の格納アドレスを調べてみよう。このプログラムの内容は、以下の通りである。まだ、詳 細は分からなくても良いが、大体の流れをつかんで欲しい。
1 #include <stdio.h>
2 int func(int i, int j);
3
4 /*======================================================*/
5 /* メイン関数 */
6 /*======================================================*/
7 int main(void){
8
9 int i;
10
11 printf("--- address -----------\n");
12 printf("\tmain\t%p\n", main);
13 printf("\tfunc\t%p\n", func);
14 printf("\tmain-i\t%p\n",&i);
15
16 i=func(5,3);
17
18 return 0;
19 }
20
21 /*======================================================*/
22 /* func 関数 */
23 /*======================================================*/
24 int func(int i, int j){
25
26 printf("\tfunc-i\t%p\n",&i);
27 printf("\tfunc-j\t%p\n",&j);
28
29 return i*j;
30
31 }
--- address ----------- main 0x8048368 func 0x80483eb main-i 0xbffff6b4 func-i 0xbffff690 func-j 0xbffff694実行結果から、命令とデータは図6のようになっ ていることが分かるであろう。命令である関数は、大体近くのメモリ上に配置されている。 しかし、データの内容を格納する変数は、ずっと離れてところにメモリーが割り当てられ ている。
関数の中で宣言される変数は、ローカル変数と言い、その宣言した関数でのみアクセスが 可能である。従って、同じ名前であるが、違う関数で宣言されたローカル変数は全く別物であ る。図6で分かるように、関数mainと関数 funcで同じ名前のローカル変数 i を宣言してるがメモリー上の配置は全く異 なる。このことからも、名前は同じであるが、全く違うものであることが理解できる。
ここで、理解しておくべきことは、以下の通りである。