メモリーが分からないと,ポインターは理解できない.そこで,ポインターの説明の前に, コンピューターのメモリーについて,説明する.ただし,諸君は,アセンブラ言語を既に 学習しているので,この辺りのことはある程度理解していると思う.
プログラマーはメモリーの内容について,ある程度自由に変更ができる.そのようなこと から,メモリーを意識してプログラムを作成することが重要である.アセンブラー言語を使うと なると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 を宣言してるがメモリー上の配置は全く異 なる.このことからも,名前は同じであるが,全く違うものであることが理解できる.
ここで,理解しておくべきことは,以下の通りである.