7.11 レジスタ変数
7.11.1 レジスタに保存する
関数内である変数が頻繁に参照されることがしばしばあります。例えば、グラフィックスなどの大きな情報を繰り返し文で制御する場合で、処理するべきピクセルの変換に用いられるパラメータを保存する変数は頻繁にアクセスされることになります。このように、一定の時間内で数千、数万回の参照が予想される変数は、少しでも高速なメモリに保存するべきであると考えられます。
そこで、C言語ではこのような変数をレジスタ変数として宣言することができます。レジスタ変数とは、コンピュータの内部で最も高速なレジスタと呼ばれる CPU 内の記憶領域に情報を保存することを表します。
通常の変数は主記憶装置に保存されます。主記憶装置は私たちが普段メモリと呼んでいる場所で、ハードディスクドライブなどのファイル保存用の補助記憶装置に比べて高速に動作します。これ以上に高速に動作するキャッシュメモリなども存在していますが、これらを利用するのはシステムであり、物理的な構造をシステムが隠蔽しているため、アプリケーションは利用することはできません。
そして、主記憶装置やキャッシュメモリ異常に高速に動作するメモリがレジスタなのです。なぜならば、レジスタはCPUに含まれるメモリだからです。主記憶装置などの情報を処理する場合、CPUが計算を行うために値を読み込む必要があります。この処理はC言語では見ることができませんが、機械語では1つの命令になります。計算のためにメモリからCPUに値を読み込んだり、計算結果をメモリに退避させるという処理にも、CPUとメモリの通信回路に依存した時間がかかってしまうのです。
レジスタに値が保存できれば、これらの時間を短縮することが期待できます。そのため、頻繁に使われる変数は主記憶ではなくレジスタに保存することが推奨されます。レジスタ変数を宣言するには register 指定子を指定します。
register 型 変数名 ...
レジスタの数やレジスタのサイズなどは物理的なコンピュータに依存する問題です。コンパイラは register 宣言を無視することが許されており、レジスタへの保存が不可能であれば、通常の変数として扱われます。一般的な解釈としては 1 つの関数内に 2 つ程度のレジスタ変数が適当であると考えられています。ただし、レジスタ変数を過度に宣言しても問題はありません。
レジスタ変数の注意点としては、レジスタ変数は主記憶に配置されないというのが原則なので、アドレスを求めることはできません。
#include <stdio.h> int main() { register int i; register int k; i = 5; k = i * 3; printf("i = %d, k = %d\n" , i, k); return 0; }
コード1では int 型のレジスタ変数 i と k を宣言しています。この変数の値が本当にレジスタに保存されるかどうかはコンパイラに依存する問題です。コンパイラによっては register 指定子そのものを無視することも可能です。
近年のコンパイラが生成するコードは最適化が進んでいるため、下手に開発者が register 指定子などを指定する必要はなく、通常のコードでも十分に最適化されます。したがって、現在では auto 指定子と同様に register 指定子も、ほとんど利用されることはありません。