本物のC

C の基本:プログラムとメモリ


メモリ上への展開

実行可能ファイルはカーネルに対し、メモリ上へどの様なデータをどこに配置するか指定します。

カーネルはプログラムに対して専用のメモリ領域を割り振り、コードもデータもそこに配置されます。この領域は仮想アドレス空間(virtual memory space)と呼ばれます。

一般に仮想アドレス空間はメモリの空き領域を寄せ集めて構成されるのですが、実行されるプログラム側には「0x00000000 から 0xFFFFFFFF まで」という風に一続きの領域が与えられた様に見えます。「仮想」と言うのはそういう意味です。

仮想アドレス空間は

(カーネル領域)
スタック
(空き領域)
ヒープ
データセグメント
コードセグメント
(空き領域)

という構成になっていて、一番下が 0x00000000 であり一番上はコンピュータのアーキテクチャにおけるアドレスの最大値(32 ビットならば 0xFFFFFFFF 、64 ビットならば 0xFFFFFFFFFFFFFFFF)です。

カーネル領域はカーネルがそのプログラムを実行する為のデータを記憶する場所で、プログラム自身のコードからはアクセスできません。また 0x00000000 付近の空き領域は所謂「NULL ポインタ参照」が偶然何らかのデータにアクセスしない様にします。

「スタック」と「ヒープ」の間の空き領域は、この上下の領域が拡張する(スタックは下に、ヒープは上に)為に空いているのですが、それらの役割については後程説明します。

C 言語ではメモリ領域に名前を付ける事ができ、その領域をデータの記憶に使う場合は変数(variable)、命令の記憶に使う場合は関数(function)と呼びます。

宣言と定義

変数や関数に付けられた名前自体を指して識別子(identifier)と言います。

識別子は初めはabcとかfooとか只の文字の並びですが、宣言する(declare)事によりその性質、つまり変数か関数か、どういう形式のデータなのかが指定されます。更に定義する(define)事で識別子は実際のメモリ領域を割り当てられます。

ただしこれは原則であって、「変数宣言」と言いつつ定義もしたりのでまぁ呼び名はあまり信用すべきでないでしょう。