(0.2 Cプログラムの概要)
前回は計算機のハードウエアについて概説しましたが、ソフトウエアについても多少の知識が必要です。
今回はOS,テキストエディタ、C言語処理系(プリプロセッサ、コンパイラ、リンカ)の関係を紹介します
簡単なC言語のプログラムの構造を示します。レポートツールを使ってプログラム書いて実行してみましょう。
計算機の記憶装置(一次記憶装置)は前回説明した番地順に1バイトを記憶する素子を並べたもので、実行中の機械語プログラムやデータを記憶します。この記憶装置に使われるのはRAM(Random Access Memory) と呼ばれる素子で、任意の番地を高速かつ同じ速さで読み書きできるのが特徴です。演算装置と制御装置はCPU(Central Processing Unit:中央演算処理装置)にまとめられています。一般的なパソコンのCPUでも1秒間に10億回程度の演算を実行できます。
実際の計算機には、この他に入出力が必要です。主なものは
入力: キーボード、マウス、マイク入力、映像入力、CD-ROM、...
出力: グラフィックディスプレー、スピーカ、プリンタ
入出力: 二次記憶装置(HDDやSSDやUSBメモリーなど)、通信装置
(インターネットなどへつなぐ回線)、
計算機の実行中のプログラムや処理中のデータは一次記憶装置に置いています。一次記憶装置はCPUの速度に対応できる読み書き速度が求められます。
一次記憶装置とは別に、実行中ではない沢山のプログラムやデータを記憶する場所として二次記憶装置が用意されています。二次記憶装置は大容量で、電源が落ちても記憶が消えないことが重要です。
二次記憶装置として使われることが多いのはHDD(Hard disk drive:ハードディスクドライブ)です。最近は半導体素子を用いたSSD(Solid-state drive)も使われるようになって来ました。HDDに比べると速いし静かですが、まだまだ高価です。
現在一次記憶装置として使われているRAMは電源を落とすと記憶が消えること、高価であることなどの問題があります。そこで、電源を落としても記憶が消えない大容量の二次記憶装置を用意して、ここに使う可能性がある沢山のプログラムやデータを記憶しておきます。
※RAMに比べるとHDDの読み書きの速度は桁違いに遅い。RAMはどの番地のデータも数十nsでアクセスできますが、HDDは回転する円盤上に磁気で記憶しているため、記憶した場所に磁気ヘッドを動かす、頭出しに10msほどの時間がかかります。この差は100万倍です。
※ちなみに、この演習室の計算機はネッワークでつながれたHDDを使っています。
ワープロなどのプログラムは二次記憶装置に保管されている。ワープロを起動すると二次記憶装置からプログラムが読み出され一次記憶装置に書き込まれる。この後、一次記憶装置の中のワープロ・プログラムが実行されることになります。
代表的な二次記憶装置で数百Gバイトから数Tバイトの容量を持つ。
※G:ギガ 10億 T:テラ 1兆
一次記憶装置ではデータは記憶場所(メモリー番地)で区別しますが、HDDでは、データはファイル名で区別します。HDDでもデータをディスクの特定の場所に記憶するのですが、ファイル名と場所の対応表(ディレクトリ情報)をHDDの既定の場所に置くことで名前によるデータの読み書きが行える仕組みになっているのです。この ようなHDD上のデータ管理(書き込み、読み出し、検索更新削除など)はOSと呼ばれる基本ソフトにより行われます。[Windowsのファイルシステム参照]
アプリケーションを実行するための環境として提供されるソフトウエア群
※環境:個々のアプリケーションプログラムにキー入力や画面への文字の書き出しなどのプログラムまで含めるのは大変です。どのアプリケーションでも必要とされるような部分のプログラムは、共用プログラムとして用意する方が合理的です。例えば、キーボードの監視プログラムや画面への文字の書き出しプログラムなどです。OSには、このような共用プログラムが多数用意されています。準備された共用プログラムの環境の上でワープロや表計算のアプリケーションプログラムは動いています。
ワープロや表計算ソフト、その他のユーザが作成したプログラムなど。アプリケーションソフトは計算機ハードウエアの制御をシステムソフトに依頼して行うため、色々な機種の計算機で実行可能である。さらに、システムソフトにはGUIや通信などの汎用性の高いプログラムが多数用意されているので、これらを利用することでアプリケーションソフトが作り易くなる。
Applicationソフト | ユーザが作成したCプログラム、ワープロソフトなど |
Systemソフト |
OS:HDDからプログラムファイルをメモリに読込んで実行するプロセスの管理 プログラムから使われる基本的な入出力プログラム(GUI、通信等) マルチタスク、マルチユーザの実現 ソフトウエア開発と実行の環境:エディタ、Cコンパイラ、リンカ、データベース、 その他いろいろ |
ハードウエア | 制御と演算:CPU、記憶:RAM、二次記憶:HDD.入出力:キーボード、ディスプレイ、通信装置. |
※OSはApplicationプログラムをRAM上に読込んで、プログラムの決 められた場所の命令からCPUに実行をさせます。プログラムは終了するとき戻り値をOSに渡し、プログラムが正常に動作したかどうかを報告します。
複雑な手順をへて機械語のプログラムが完成するが、大きなプログラムを複数の人が分担して作成する為に用意されたもので す。一人でプログラムを作る場合も、他人の作ったライブラリを使うのでこの仕組みは必要です。
WindowsやUNIXのファイル名の最後にある「.」以下の部分を拡張子と呼ぶ。これはファイルの種類を示す名前で、UNIXや
Windows系のOSは拡張子を使ってファイルを分類する。
Windowsでは拡張子を表示しない設定がデフォルトなので気づかないかもしれないが、ア
イコンの画像が拡張子で決まっている場合も多い。ワープロやエディタをインストールするとアイコンが一斉に変る場合が有るのはこのためである。
C言語に関連した拡張子
種類 | Windows | UNIX |
Cのソースファイル | .c | .c |
Cのヘッダーファイル | .h | .h |
オブジェクトファイル | .obj | .o |
ライブラリファイル | .lib、 .dll | .a、 .sdl |
実行ファイル | .exe | 実行可能性は拡張子によらない |
※拡張子が.ccとか.cppの場合C言語ではなくてC++言語のソースファイルと見なされるので注意
※.libは静的リンクライブラリ、.dllは動的リンクライブラリ
「Hallo」と書き出すだけのプログラムを動かすにも、ソースファイルを作ってコンパイルしリンクして実行ファイルを作り。これをOSに命令して実行してもらう必要があります。とても煩雑です。
そこで、GUIのボタン操作でCプログラムの作成と実行が行える自作のレポートツールを用意しました。簡単なプログラムならレポートツールで動かすことができます。
C言語はさまざまな計算機で使われる様になりましたが、文法に方言が現れることにもなりました。そこで、プログラム言語の 研究成果を取り入れ、より安全で大規模なプログラムを作成できるように、またソースプログラムの共用が可能なように方言の幅を減らし、標準のライブラリを 用意するなど、標準化が行われてきました。
1990年前後の俗にANSI-Cとよばれる標準C89やC90。そして、新しい規格:C99(1999年)やC11(2011年)がANSIの標準に加えられています。しかし、ここではC89に沿った説明を中心に行います。
※C99では変数の宣言位置がブロック先頭以外でも可能だったり、インライン関数が記述できたり 、複素数や論理値型が使えたりと便利になった部分も多いので、C++ではなくてC言語を仕事で使うような場合は、このC99を 知っておくことが必要になります。しかし、C++やjavaを学ぶ上では、このC99で追加された部分を特に必要としない。説明する必要のある概念が増える。市販のC言語処理系が いまだに十分に対応していない。などの理由で序論ではC89に沿った説明としました。
※教科書はC11にも対応しています。しかし、入門なので、新しい機能についてはほとんど触れられていません。
C言語のプログラムは関数を単位として書く決まりです。長いプログラムは複数の関数に分割して書かれます。
関数はデータを受け取って処理を行い、1つの値を戻して終了する小さなプログラム部品です。関数の中から別の関数を呼びだすことができます。これにより、関数から関数を呼ぶことで複雑で大きなプログラムを作ることが可能です。
プログラムは複数の関数から構成されますが、実行開始で実行する関数の名前は決められています。
C言語のプログラムの実行はmain関数の実行と決められています。
※通常はmain関数の中で他の関数を呼んで実行する形のプログラムを作ります。main関数から始まる関数の呼び出しの順番で関数が実行されますから、プログラムに関数を記述した順番と関数が実行される順番とは無関係です。
※複数の関数を書く場合にmain関数を最初に書く必要はありません。main関数が最後に書かれたプログラムでも実行はmain関数から始まります。
従って、C言語で実行可能プログラムを作るにはソースプログラムにmain関数を書かなければいけません。
main関数は次のような形をしています。
int main(void) { /*この部分にいろいろ書く*/ return 0; }
最初の1行に書かれた部分を関数の頭部といいます。この部分に関数名と関数に渡すデータと受け取れるデータのタイプなど関数を呼ぶときに必要とする情報がまとめられています。
○mainが関数名です。
○関数名の前のintは関数が戻すデータのタイプで、intは整数(integer)型の意味です。
○関数名の後の(void)は関数に渡すデータのタイプを示していて、voidは何も渡さないことを示します。
2行目から後の{から}までがmain関数のプログラムを記述する部分で関数の本体と言います。
main関数の形は他にもあるのですが、当面これしか使いません。まずはこれを暗記してください。
関数本体に書かれたreturnは関数から戻る(return)命令です。関数が戻す値を0として戻る場合はreturn 0; のように書きます。
※プログラムを起動したOS側で戻り値を受け取り、例えば0が戻されればプログラムが正常に動作した と判断するのに使うことが出来ます。
例題にある「/*」と「*/」で囲んだ部分と「//」から改行までの部分は、コンパイル時には1個の区切り文字と解釈されます。これは注釈を書く為に用意された決まりで、機械語への翻訳では中身に関係なく1個の区切文字と見なされます。
区切り文字は空白文字、改行文字、タブ文字などで単語や文の区切りを示します。コンパイラは連続した空白文字や注釈等を1個の区切り文字と見なして翻訳します。 この結果、プログラムを書く時の区切りの空白や空行や注釈を色々変えても、翻訳して作られる機械語のプログラムは同じものに成ります。(教科書6pのリスト0_1,0_2)。このようなC言語の書式を自由書式(フリーフォーマット)と言います。
※改行、空白、空行、タブ、注釈等でプログラムを人間に読み やすくすることが大事です。ただ、標準的な書き方が有るので、独自の書き方はやめて、教科書の書き方に従ってください。
※スラッシュ2個「//」で始まるコメントもC99からは認められています。//から行末までがコメントになります。
関数の実行は呼び出しと言われる形式で行われます。呼び出しはcallの日本語訳です。呼び出し命令はプログラムの途中から呼び出す関数の先頭にプログラムの実行位置を変えます。このとき元のプログラムに戻れるように、戻る場所を保存しておくので、呼び出し先の関数で帰る命令(return)を実行すると戻ってこれます。main関数の場合もreturnで終わることでOSに戻 ります。
※呼び出す相手の関数はリンクの時に関数名で検索して見つけ、関数の場所を機械語のcall命令の跳び先番地として書き込みます。call命令が実行されるとcall命令の直後の番地を戻る場所として記憶した後、関数の機械語プログラムの先頭へと実行位置を変えます。関数のreturn命令が実行されると記憶された戻り番地に実行位置が戻ります。
関数の本体には他の関数を呼び出す命令を書くことが出来ます。しかし、関数を呼び出すときは、その関数に「どの様に値を渡し、戻ってきたときにどの様に値を受け取るのか」分っていることが必要です。なぜなら、関数に渡す値を用意し、関数から帰ってきたら戻り値を受け取る機械語プログラムに翻訳するからです。
※call命令の直前には、呼び出す関数に渡すデータを作る機械語プログラムが置かれます。直後には関数からの戻り値を受け取る機械語が置かれます。
以下に標準ライブラリに用意されたprintf関数を呼びだすプログラム例を示します。ここで関数に渡す値と戻り値の情報が書かれたヘッダーファイル:stdio.hを前処理でプログラムに挿入するため、#include<stdio.h>が必要なので忘れないでください。
何もしないプログラムに赤い太字で示すような部分を加えることでmain関数の中からpritf関数を呼び出して画面に「Hello World」と書き出すことができます。
/* コメント ソースファイル hello.c オブジェクトファイル hello.obj 実行可能ファイル hello.exe */ #include<stdio.h> /*前処理への指示*/ /*main関数*/ int main(void) { printf("Hello World\n");/*printf関数呼び出し*/ return 0; /*戻り値で0を戻す */ }
※stdio.hは標準(standard)入出力(input output)のヘッダーファイル(header file)。標準ライブラリには機械語に翻訳済みの多数の関数プログラムが用意してあります。 stdio.hにはライブライの内で標準入出力関数について関数名、渡す値と、戻り値の情報をコンパイラに教えるプロトタイプ宣言と呼ばれるものが書かれています。
(注意:ヘッダーファイルには関数のソースプログラムが書いてあるわけではありません。関数へのデータの渡し方と結果の受け取りかた、が書かれているだけです。)
※この例では、includeを忘れても、警告は出ますがコンパイルされ、実行もできる。しかし、printf関数の使い方次第で、実行時エラーが出ます。
※main関数は通常では他の関数から呼ばれることはありません。実行を開始する関数として名前や戻り値などは決められているので、改めてプロトタイプ宣言は不要ですし、行いません。
C言語処理系で作られる実行可能プログラムはmain関数を実行するプログラムと成ります。
main関数の中で他の関数が使われていれば、それらがmain関数から呼び出されることで、1 つのまとまったプログラムとしての処理を行うことになります。
例のプログラムではmain関数が最初に 呼び出され、main関数の中からprintf関数が呼び出されます。次の図の赤い線で示す順番に命令が実行されます。関数mainの途中から呼び出しで関数printfの先頭に処理が移動しますが、printfの処理が終わると元の場所の次の処理に戻ってきます。
自作のレポートツールを用意しました。今日の話の演習課題として
学籍番号と名前を書き出すプログラムを作って実行し、実行結果をPrint ScreenかSnipping Toolを使用して
jpeg画像として保存してください(後程レポート作成に必要となります)。