コンピュータサイエンスにおいて、命令型プログラミングは、計算がどのように行われるべきかについての具体的な指示を提供するソフトウェアプログラミングパラダイムです。このパラダイムでは、プロセスの状態を変更する可能性のあるステートメントを使用する場合があります。自然言語の命令法がコマンドを表現するのとほぼ同じように、命令型プログラムは、コンピュータが実行するコマンドで構成されます。命令型プログラミングは、期待される結果の高レベルな記述ではなく、プログラムがどのように段階的に動作するかを記述することに重点を置いています(ステップの順序は、一般的にソースコード内でステートメントを上下に配置することによって決定されます)[ 1 ]。
この用語は、プログラムが何を達成すべきかに焦点を当て、プログラムが結果を達成する方法の詳細をすべて指定しない宣言型プログラミングと対比してよく使用されます。 [ 2 ]
手続き型プログラミングは、プログラムが 1 つ以上の手続き (サブルーチンまたは関数とも呼ばれる) から構築される命令型プログラミングの一種です。これらの用語はしばしば同義語として使用されますが、手続きの使用は命令型プログラムの外観と構築方法に劇的な影響を与えます。状態変更が手続き内に限定されるか、手続きからの明示的な引数と戻り値に限定される、重度の手続き型プログラミングは、構造化プログラミングの一形態です。1960 年代以降、構造化プログラミングとモジュール型プログラミング全般は、命令型プログラムの保守性と全体的な品質を向上させる技術として推進されてきました。オブジェクト指向プログラミングの背後にある概念は、このアプローチを拡張しようとしています。
手続き型プログラミングは、宣言型プログラミングへの一歩と考えることができる。プログラマーは、手続きの名前、引数、戻り値の型(および関連するコメント)を見るだけで、特定の手続きが何をするべきかを、結果を得る方法の詳細を必ずしも確認しなくても、多くの場合理解できる。同時に、完全なプログラムは、実行されるステートメントとその実行順序を大部分において固定するため、依然として命令型である。
ほぼすべてのコンピュータのプログラムを構築するために使用されるプログラミングパラダイムは、通常、命令型モデルに従います。[注1 ]デジタルコンピュータハードウェアは、コンピュータ固有のマシンコードを実行するように設計されており、マシンコードは通常、命令型スタイルで記述されますが、Lispマシンなどの一部のアーキテクチャでは、他のパラダイムを使用する低レベルコンパイラとインタプリタが存在します。
この低レベルの視点から見ると、プログラムの状態はメモリの内容によって定義され、ステートメントはコンピュータのネイティブマシン語の命令です。より高レベルの命令型言語は変数やより複雑なステートメントを使用しますが、それでも同じパラダイムに従います。レシピやプロセスチェックリストはコンピュータプログラムではありませんが、命令型プログラミングとスタイルが似ている馴染みのある概念です。各ステップは命令であり、物理世界が状態を保持します。命令型プログラミングの基本的な考え方は概念的に馴染みがあり、ハードウェアに直接具現化されているため、ほとんどのコンピュータ言語は命令型スタイルです。
命令型プログラミングにおける代入文は、メモリに格納されている情報に対して演算を実行し、その結果を後で使用するためにメモリに格納します。高水準命令型言語では、さらに、算術演算と関数評価の組み合わせで構成される複雑な式の評価と、その結果の値をメモリに代入することができます。ループ文(while ループ、do while ループ、for ループなど)を使用すると、一連の文を複数回実行できます。ループは、含まれる文をあらかじめ定義された回数だけ実行することも、何らかの条件が満たされるまで繰り返し実行することもできます。条件分岐文を使用すると、一連の文を何らかの条件が満たされた場合にのみ実行できます。そうでない場合は、文はスキップされ、実行シーケンスは次の文から続行されます。無条件分岐文を使用すると、実行シーケンスをプログラムの別の部分に転送できます。これには、ジャンプ(多くの言語ではgotoと呼ばれます)、switch、サブルーチン、プロシージャ呼び出し(通常は呼び出し後の次の文に戻ります)などがあります。
高水準プログラミング言語の開発初期において、ブロックの導入により、一連のステートメントや宣言をあたかも一つのステートメントであるかのように扱うプログラムの構築が可能になった。これは、サブルーチンの導入と相まって、複雑な構造をより単純な手続き構造へと階層的に分解することで表現することを可能にした。
初期の命令型言語は、初期のコンピュータの機械語でした。これらの言語では命令が非常に単純だったため、ハードウェアの実装は容易でしたが、複雑なプログラムの作成は困難でした。
1954年にインターナショナル・ビジネス・マシーンズ(IBM)のジョン・バッカスによって開発されたFortranは、複雑なプログラムの作成において機械語がもたらす障害を取り除いた最初の主要なプログラミング言語でした。Fortranはコンパイル言語であり、名前付き変数、複雑な式、サブルーチンなど、現在では命令型言語で一般的な多くの機能を可能にしました。
続く20年間には、他にも多くの主要な高水準命令型プログラミング言語が開発された。1950年代後半から1960年代にかけて、数学的アルゴリズムをより容易に表現できるようにするためにALGOLが開発され、一部のコンピュータではオペレーティングシステムのターゲット言語としても利用された。
MUMPS(1966年)は、命令型パラダイムを論理的に極限まで推し進め、文を一切持たず、純粋にコマンドのみに依存し、IFコマンドとELSEコマンドさえも互いに独立させ、$TESTという名前の組み込み変数でのみ接続するという徹底ぶりだった。COBOL (1960年)とBASIC (1964年)はどちらも、プログラミング構文を英語に近づけようとする試みだった。
1970年代には、Pascalはニクラウス・ヴィルトによって開発され、C言語はベル研究所に勤務していたデニス・リッチーによって作成されました。ヴィルトはその後、Modula-2とOberonを設計しました。米国国防総省のニーズに応えるため、ハネウェルのジャン・イチビアとチームは、言語の要件を定義する4年間のプロジェクトを経て、1978年にAdaの設計を開始しました。仕様は1983年に初めて公開され、1995年、2005年、2012年に改訂されました。
1980 年代にはオブジェクト指向プログラミングへの関心が急速に高まりました。これらの言語は命令型スタイルでしたが、オブジェクトをサポートする機能が追加されました。20 世紀の最後の 20 年間には、このような言語が多数開発されました。1969年にAlan Kayによって考案されたSmalltalk -80 は、1980 年に Xerox Palo Alto Research Center ( PARC ) によってリリースされました。別のオブジェクト指向言語であるSimula ( 1960 年代に開発された世界初のオブジェクト指向プログラミング言語と考えられている) の概念を取り入れて、 Bjarne Stroustrup はCをベースにしたオブジェクト指向言語であるC++を設計しました。C ++の設計は1979 年に始まり、最初の実装は 1983 年に完了しました。1980 年代後半から 1990 年代にかけて、オブジェクト指向の概念を取り入れた注目すべき命令型言語としては、 1987 年にLarry WallによってリリースされたPerlがありました。 PythonはGuido van Rossumによって1990 年にリリースされました。Visual BasicとVisual C++ ( Microsoft Foundation Class Library (MFC) 2.0を含む) は、それぞれMicrosoftによって1991 年と 1993 年にリリースされました。PHPはRasmus Lerdorfによって1994 年にリリースされました。JavaはJames Gosling ( Sun Microsystems )によって1995 年にリリースされました。JavaScriptはBrendan Eich ( Netscape )によって、Rubyは Yukihiro "Matz" Matsumoto によって 1995 年にリリースされました。Microsoft の.NET Framework (2002) は、そのコアにおいて命令型であり、その上で動作する主なターゲット言語であるVB.NETとC#も同様です。ただし、関数型言語である Microsoft のF#もその上で動作します。
Fortran(1958年)は「IBM数式翻訳システム」として発表されました。文字列処理機能を持たない科学計算用に設計されました。宣言、式、ステートメントに加えて、以下の機能をサポートしていました。
成功した理由は以下のとおりです。
しかし、IBM以外のベンダーもFortranコンパイラを作成しましたが、その構文はIBMのコンパイラではエラーになる可能性が高いものでした。[ 3 ]米国規格協会(ANSI)は1966年に最初のFortran規格を策定しました。1978年にはFortran 77が標準となり、1991年まで使用されました。Fortran 90は以下をサポートしています。
COBOL (1959) は「共通ビジネス指向言語」の略です。Fortran はシンボルを操作していました。シンボルは数値である必要がないことがすぐに認識され、文字列が導入されました。[ 4 ]米国国防総省はCOBOL の開発に影響を与え、グレース・ホッパーが主要な貢献者でした。ステートメントは英語に似ていて冗長でした。目標は、管理者がプログラムを読める言語を設計することでした。しかし、構造化されたステートメントの欠如がこの目標を妨げました。[ 5 ]
COBOLの開発は厳密に管理されていたため、ANSI規格を必要とする方言は出現しなかった。その結果、1974年まで15年間変更されなかった。1990年代のバージョンでは、オブジェクト指向プログラミングなどの重要な変更が加えられた。[ 5 ]
ALGOL(1960)は「ALGOrithmic Language」の略です。プログラミング言語設計に大きな影響を与えました。[ 6 ]ヨーロッパとアメリカのプログラミング言語専門家からなる委員会から生まれたALGOLは、標準的な数学的記法を使用し、読みやすい構造設計を採用していました。ALGOLは、バッカス・ナウア記法を用いて構文を定義した最初の言語でした。[ 6 ]これにより、構文指向コンパイラが誕生しました。ALGOLは次のような機能を追加しました。
ALGOLの直接の子孫には、 1つの系統にPascal、Modula-2、Ada、Delphi、Oberonがある。別の系統にはC、C++、Javaがある。[ 6 ]
BASIC (1964) は「Beginner's All Purpose Symbolic Instruction Code」の略です。ダートマス大学で、全学生が学習できるように開発されました。[ 7 ]学生がより強力な言語に進まなくても、BASIC は覚えておくことができます。[ 7 ] 1970 年代後半に製造されたマイクロコンピュータには BASIC インタープリタがインストールされました。マイクロコンピュータ産業が成長するにつれて、この言語も成長しました。[ 7 ]
BASICは対話型セッションの先駆けとなった。[ 7 ] BASICは、その環境内でオペレーティングシステムのコマンドを提供した。
しかし、BASIC構文は大規模プログラムには単純すぎた。[ 7 ]最近のBASIC方言では、構造とオブジェクト指向の拡張機能が追加されている。MicrosoftのVisual Basicは今でも広く使われており、グラフィカルユーザーインターフェースを生成する。[ 8 ]
C言語(1973年)は、 BCPL言語がB言語に置き換えられた際に、AT&Tベル研究所が次のバージョンを「C」と名付けたことからその名が付けられました。その目的はUNIXオペレーティングシステムを開発することでした。[ 9 ] C言語は比較的小規模な言語であるため、コンパイラの作成が容易です。その成長は1980年代のハードウェアの成長と軌を一にしていました。[ 9 ]また、アセンブリ言語の機能を備えながらも高水準構文を使用していることも、成長の要因の一つでした。C言語には以下のような高度な機能が追加されました。

C言語では、プログラマがメモリのどの領域にデータを格納するかを制御できます。グローバル変数と静的変数は、格納に必要なクロックサイクルが最も少なくて済みます。スタックは、標準変数宣言に自動的に使用されます。ヒープメモリは、関数からポインタ変数に返されますmalloc()。
main()が格納されます。[ 11 ]main()グローバル変数は、ソースコード内の他のすべての関数から参照可能です。main()、他の関数、または{}ブロック区切り文字内の変数宣言はローカル変数です。ローカル変数には仮パラメータ変数も含まれます。パラメータ変数は関数定義の括弧で囲まれます。[ 12 ]これらは関数への インターフェースを提供します。static(仮引数変数を含む) [ 14 ]は自動変数[ 11 ]と呼ばれ、スタックに格納されます。[ 10 ]それらは関数またはブロック内では可視であり、関数またはブロックを抜けるとスコープを失います。malloc()ライブラリ関数を提供します。[ 16 ]ヒープにデータを格納するのは、追加のコピー関数です。ヒープに格納された変数は、ポインタを使用して効率的に関数に渡されます。ポインタがない場合、データのブロック全体をスタック経由で関数に渡す必要があります。1970年代、ソフトウェアエンジニアは大規模プロジェクトをモジュールに分割するための言語サポートを必要としていました。[ 17 ] 1つの明白な機能は、大規模プロジェクトを物理的に個別のファイルに分解することでした。あまり明白ではない機能は、大規模プロジェクトを論理的に抽象データ型に分解することでした。[ 17 ]当時、言語は整数、浮動小数点数、文字列などの具体的な(スカラー)データ型をサポートしていました。具体的なデータ型は、その表現が名前の一部になっています。[ 18 ]抽象データ型は、具体的なデータ型の構造であり、新しい名前が割り当てられています。たとえば、整数のリストはと呼ばれることがあります。integer_list
オブジェクト指向の専門用語では、抽象データ型はクラスと呼ばれます。ただし、クラスは定義にすぎず、メモリは割り当てられません。クラスにメモリが割り当てられると、それはオブジェクトと呼ばれます。[ 19 ]
オブジェクト指向命令型言語は、クラスの必要性と安全な関数型プログラミングの必要性を組み合わせることによって開発されました。 [ 20 ]オブジェクト指向言語では、関数はクラスに割り当てられます。割り当てられた関数は、メソッド、メンバ関数、または操作と呼ばれます。オブジェクト指向プログラミングは、オブジェクトに対して操作を実行することです。 [ 21 ]
オブジェクト指向言語は、部分集合/上位集合の関係をモデル化する構文をサポートしています。集合論では、部分集合の要素は上位集合に含まれるすべての属性を継承します。たとえば、学生は人です。したがって、学生の集合は人の集合の部分集合です。結果として、学生はすべての人間に共通するすべての属性を継承します。さらに、学生は他の人にはない固有の属性を持っています。オブジェクト指向言語は、継承を使用して部分集合/上位集合の関係をモデル化します。[ 22 ]オブジェクト指向プログラミングは、1990年代後半までに支配的な言語パラダイムになりました。[ 17 ]
C++(1985年)は当初「クラス付きC」と呼ばれていました。[ 23 ]これは、言語Simulaのオブジェクト指向機能を追加することでCの機能を拡張するように設計されました。[ 24 ]
オブジェクト指向モジュールは2つのファイルで構成されます。定義ファイルはヘッダーファイルと呼ばれます。以下は、シンプルな学校アプリケーションのGRADEクラスのC++ヘッダーファイルです。
// grade.h // -------// 複数のソースファイルが重複エラーなしでこのヘッダーファイルを含めることを可能にするために使用されます。 // 参照: https://en.wikipedia.org/wiki/Include_guard // ---------------------------------------------- #ifndef GRADE_H #define GRADE_Hclass GRADE { public : // これはコンストラクタ操作です。// ---------------------------------- GRADE ( const char letter );// これはクラス変数です。// ------------------------- char letter ;// これはメンバ操作です。// --------------------------- int grade_numeric ( const char letter );// これはクラス変数です。// ------------------------- int numeric ; }; #endifコンストラクタ操作は、クラス名と同じ名前の関数です。[ 25 ]呼び出し元の操作がnewステートメントを実行するときに実行されます。
モジュールのもう1つのファイルはソースファイルです。以下は、シンプルな学校アプリケーションのGRADEクラスのC++ソースファイルです。
// grade.cpp // --------- #include "grade.h"GRADE :: GRADE ( const char letter ) { // キーワード 'this' を使用してオブジェクトを参照します。// ---------------------------------------------- this -> letter = letter ;// これは時間的凝集性です// ------------------------- this -> numeric = grade_numeric ( letter ); }int GRADE :: grade_numeric ( const char letter ) { if ( ( letter == 'A' || letter == 'a' ) ) return 4 ; else if ( ( letter == 'B' || letter == 'b' ) ) return 3 ; else if ( ( letter == 'C' || letter == 'c' ) ) return 2 ; else if ( ( letter == 'D' || letter == 'd' ) ) return 1 ; else if ( ( letter == 'F' || letter == 'f' ) ) return 0 ; else return -1 ; }以下は、シンプルな学校向けアプリケーションにおけるPERSONクラスのC++ヘッダーファイルです。
// person.h // -------- #ifndef PERSON_H #define PERSON_Hclass PERSON { public : PERSON ( const char * name ); const char * name ; }; #endif以下は、シンプルな学校向けアプリケーションにおけるPERSONクラスのC++ソースファイルです。
// person.cpp // ---------- #include "person.h"PERSON :: PERSON ( const char * name ) { this -> name = name ; }以下は、シンプルな学校向けアプリケーションにおけるSTUDENTクラスのC++ヘッダーファイルです。
// student.h // --------- #ifndef STUDENT_H #define STUDENT_H#include "person.h" #include "grade.h"// STUDENT は PERSON のサブセットです。// -------------------------------- class STUDENT : public PERSON { public : STUDENT ( const char * name ); ~ STUDENT (); GRADE * grade ; }; #endif以下は、シンプルな学校向けアプリケーションにおけるSTUDENTクラスのC++ソースファイルです。
// student.cpp // ----------- #include "student.h" #include "person.h"STUDENT :: STUDENT ( const char * name ) : // PERSON スーパークラスのコンストラクタを実行します。// ------------------------------------------------- PERSON ( name ) { // 他に何もする必要はありません。// ------------------- }STUDENT ::~ STUDENT () { // メモリリークを防ぐため、成績のメモリを解放します。// ------------------------------------------------- delete this -> grade ; }以下は、デモンストレーション用のドライバプログラムです。
// student_dvr.cpp // --------------- #include <iostream> #include "student.h"int main ( void ) { STUDENT * student = new STUDENT ( "The Student" ); student -> grade = new GRADE ( 'a' );std :: cout // 学生がPERSONの名前を継承していることに注意<< student- > name << ": 数値成績 = " << student- > grade- > numeric << " \n " ;// メモリリークを防ぐため、学生のメモリを解放します。// ------------------------------------------------- delete student ;return 0 ; }以下は、すべてをコンパイルするためのメイクファイルです。
# makefile # -------- all : student_dvrclean : rm student_dvr *.o student_dvr : student_dvr.cpp grade.o student.o person.o c ++ student_dvr.cpp grade.o student.o person.o -o student_dvrgrade.o : grade.cpp grade.h c ++ -c grade.cppstudent.o : student.cpp student.h c ++ -c student.cppperson.o : person.cpp person.h c ++ -c person.cpp