メモリーが分からないと,ポインターは理解できない.そこで,ポインターの説明の前に, コンピューターのメモリーについて,説明する.ただし,諸君は,アセンブラ言語を既に 学習しているので,この辺りのことはある程度理解していると思う.
プログラマーはメモリーの内容について,ある程度自由に変更ができる.そのようなこと から,メモリーを意識してプログラムを作成することが重要である.アセンブラー言語を使うと なるとCPUについても意識が必要であろうが,C言語ではそこまで要求しない.
メインメモリーの役目は,命令とデータからなるプログラムを記憶することである.そのプロ グラムは全て,0と1の数字で表せ,2進数で表現可能である.どのようなモデルでこの2進 数が格納されているか学習する.
プログラムという情報は記憶するだけでは全く役に立たない.記憶した内容を取り出せて 初めて,活用ができる.そこで,メモリーは記憶するための住所が決められている.この 住所のことをアドレス(address)と言い,0から整数の番地がふってある.諸君が使ってい るパソコンのアドレスは32ビットで表現されている3.そして,一つの番地には,8個の0と1が記憶 できる.この様子を図2に示す.
図を見て分かるとおり,2進数の表現は桁数が多くて人間にとって大変である4.そこで,通常は,2進数の4桁をまとめて,16進数で 表す.そうすると,アドレスは16進数8桁,記憶内容は16進数2桁で表すことができ,分か りやすくなる.その様子を図3に示す.
ついでに述べておくが,1個の0あるいは1の情報量を1ビットと言う.8ビットで1バイトと 言う.従って,メインメモリーの一つの番地(アドレス)には,1バイト(8ビット)の情報が 記憶できる.
メモリーについて覚えておくことは,以下の通りである.
それでは,実際にメモリーにデータが格納する様子を見よう.次のようにプログラムに書 いたとする.
double x=-7.696151733398438e-4; int i=55; char a='a';それぞれのデータは,
鋭い学生は,データの並びが逆であることが分かるであろう.例えば,整数のiであ るが, なので, と並ぶと考えられるが,実際は図 4の通り逆である.これは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実行結果から,命令とデータは図5のようになっ ていることが分かるであろう.命令である関数は,大体近くのメモリ上に配置されている. しかし,データの内容を格納する変数は,ずっと離れてところにメモリーが割り当てられ ている.
関数の中で宣言される変数は,ローカル変数と言い,その宣言した関数でのみアクセスが 可能である.従って,同じ名前であるが,違う関数で宣言されたローカル変数は全く別物であ る.図5で分かるように,関数mainと関数 funcで同じ名前のローカル変数 i を宣言してるがメモリー上の配置は全く異 なる.このことからも,名前は同じであるが,全く違うものであることが理解できる.
ここで,理解しておくべきことは,以下の通りである.