再帰的(リカーシブ)・再入可能(リエントラント)・再使用可能・再配置可能

紛らわし首記4つの用語についてまとめ。

再帰的(リカーシブ)

プログラムを1つでも学んだことがあるなら、階乗を求める関数を見たことがあると思うが、
あれがまさしく再帰処理をしている。

int factorial(int n){
    if(n==0){
        return 1;
    }else{
        return factorial(n-1) * n;
    }
}

上記は階乗を求めるC言語の関数であるが、factorial()という関数の中で、factorial()を、
つまり自分自身を呼び出している。これがまさに再帰的であるということである。
殆どすべてのプログラム言語で、再帰処理は実行可能である。
BASICでさえ、書き方を工夫すれば再帰処理を実装することができる。

再入可能(リエントラント)

業界的には「リエントラント」の方が通じるらしいので、以降ではこちらで書き進める。
リエントラントな処理とは、その処理を実行中に、更に同じ処理が呼び出されたとしても、
両方の処理が正しく処理を完了できる、ということである。
まずは、この「更に同じ処理が呼び出される」という状況であるが、
以下の3つのパターンがある:

  1. ある処理を実行中にその処理自身が自分を呼び出す
  2. ある処理を実行中に割り込みが入り、その割り込み処理がその処理を呼び出す
  3. 別々の場所で、同じ処理が呼び出される

このうち、1)は先に紹介した再帰処理である。したがって、再帰処理はリエントラントである。
2)が、純粋なリエントラントである。一方、3)は「スレッドセーフ」と言われる特性であり、
厳密にはリエントラントとは別の概念である。

再使用可能

プログラムの実行には、①まず記憶装置からプログラムコードを読み取りメモリに配置してから、②メモリに配置したプログラムコードを実行する、という2つのステップを踏む。
複数のソフトウェアが同じプログラムコードを使用したい時、別々にメモリに配置してそれぞれがプログラムを実行しているのは無駄である。
可能であるならば、一度メモリに配置したプログラムコードを、複数のソフトウェアが共有して使うのが望ましい。これができるプログラムを「再使用可能」なプログラムと呼ぶ。
この再使用可能なプログラムが、複数ソフトウェアから同時に呼ばれたときに、
同時に処理を実行できるならば、このプログラムはリエントラントでもある。
しかし、リエントラントではないプログラムでも、再使用可能にすることはできる。
このようなプログラムは特に「逐次再使用可能」であると言う。

再配置可能

再配置可能を説明するためには、まずはメモリアドレスについて知らなければなりません。
プログラムは機械語の命令をつなげたものです。しかし一直線につなげたのでは分岐処理ができません。
分岐処理というと、ifやらforやらswitchやらがありますが、機械語の命令に直すタイミングで、
おおよそジャンプ命令に置き換わります。
ジャンプ命令とは「○○に移動し、そこから命令を始めよ」という命令であり、
C言語で言えばあの悪名高いgotoのことです。
コーディングのマナー、あるいはルールとしてgoto命令を使うなということは色々なところで
言われていますが、実は機械語の世界ではgotoのオンパレードなのですね。
さて、gotoを使うとなると、ジャンプする先を指定しなければいけません。
これをどうやって指定するかという時に、メモリアドレスの話か出てきます。
プログラムは実行時にメモリ上に配置されますから、ジャンプ先として指定するのは
メモリのアドレスになります。この時、

  • 「xx番メモリへ移動せよ」と命令するのが絶対アドレスによるジャンプ命令
  • 「ここからnn先のメモリへ移動せよ」と命令するのが相対アドレスによるジャンプ命令

となります。
絶対アドレスによるジャンプ命令を使うとなると、このプログラムがメモリに配置される際に、
その場所は固定されていなければいけません。そうしないと、配置場所が変わるたびに、
ジャンプしたい先のメモリ位置が変わってしまうからです。
一方、相対アドレスによるジャンプ命令であれば、このプログラムはメモリのどこに配置さても
問題ありません。
再配置可能なプログラムの書き方の一つの方法は、相対アドレスによるジャンプ命令だけで
プログラムを作るという方法です。
他の手法としては、仮想アドレスでメモリ管理するというものもあり、実はこちらの方が主流です。