第四話 最初のプログラムの解説
ここで俺はふと気付いた。
「でもこれってさ、a.exeって名前しか作れないの?」
「あっ。いい所に気がついたわね」
誰でも気付くって……。俺はそう心の中で突っ込みを入れる。
「実はね、オプションを追加することで、名前を付けられるの。さっきのgccの命令の後にスペースキーを入れて、-o firstprogram って入れて」
俺はカタカタと打ってみる。
>gcc firstprogram.c -o firstprogram [ENTER]
「で、DIRコマンドで確認ね」
カタカタカタ。
すると、sampleフォルダ内に、firstprogram.exeが追加されていた。サイズは22,526なのでa.exeと同じだ。
試しに実行してみたら、例の先輩の嘘発言が表示される。
「なるほど」
「今回ソースと同じ名前にしたけど、-oの後の名前は自由に付けられるわよ。これから、ずっと -oオプションは使うからね。全部a.exeじゃ区別つかなくなっちゃうでしょ。あと――」
立花先輩は、さらに続けた。
「もうひとつ。-Wallオプションも個人的におすすめ。これも付けるからね」
「-Wallオプション?」
「これ入れると、Warning all、すべての警告を表示する設定ね」
「警告?」
「うん。プログラムでエラー、つまり明白な間違いじゃないけど、ちょっと怪しいんじゃないかなー、って部分をコンパイラが親切に教えてくれるの。これで、より間違ったプログラムが作りにくくなるわけね」
「うーむ。まるで先輩のような厳しい突っ込みになるのか」
「なんか言った?」先輩の目がすっと細くなる。こ、怖い……。
「な、なんでもないです……」
「おほん。じゃ、これからプログラムの解説をするわよ。よーく聞いてなさい」
「はい」
立花先輩は、firstprogram.cをテキストエディタで開いた。
/* 最初のプログラム! */
#include <stdio.h>
int main(void)
{
printf("立花アカネは、世界一の美少女デス♪\n");
return 0;
}
「さて、まずは、プログラムの構造から説明するわよ。最初の/* */で挟まれているのはコメント。これはコンパイラは完全に無視するから、ここに日本語でプログラムの説明とか入れておくの。で、次の#includeのとこは、とりあえず後回し」
「そ、そうですか」
「で、int main(void)ってのが、このプログラムのメイン部分ね。mainのところがタイトルで、前後のint と(void)は、後で説明するわ。で、次の{}の間にあるのが中身だと思って。こういうのは関数、ファンクションっていうの」
先輩はカーソルをmainのタイトルへと持っていった。
「このプログラムはmainの一つしかないけど、普通は何百もの関数で一つのプログラムは構成されてるわ。もっとも、どんな長いプログラムにも、必ずmain関数はあって、そこから常にCのプログラムはスタートするの。パソコンのOS、この機種だとWindowsから呼ばれるわけ」
うむ、結構、プログラムってのも単純なものだな。
「この間には、二つの行があるのか」
「うん。それぞれの行の最後には必ず『;』がついて、ここが行の最後ですとコンパイラに教えているの。で、イツキくんももう解っていると思うけど、これは文章を一行表示するプログラム。printf()文のところがそれね。これもprintf()関数っていうのよ。二つの『”』マークの間にある文章を画面に表示してって命令」
「printf()関数? その中身はここに書かれていないのですか?」
「じつはね、一行目の#include <stdio.h>の中のstdio.hって所にprintf()関数の定義があるの。詳しくはちょっと違うけど、今はそう思って頂戴。このパソコンのある場所に、stdio.hって名前のコードがあって、そこの中にprintf()関数の中身が書かれていると思って。で、このインクルード命令を入れると、それを、このプログラムに読み込んでってパソコンに命令するの。これ入れないと、このプログラム内でprintf()関数は使えないわ」
「文の最後の\nってなんですか?」
「これは、ここで改行してって命令。これしないと、たとえば二行書いてたら、くっついちゃって表示されるでしょ」
「ふむふむ」
「で、次のreturn 0っていうのは、この関数はリターン、ここで終了するよー、とOSに教えているの。このプログラムの構造、図にすると、こんな感じね」
先輩は、コードの端っこにカリカリと書き始めた。
Windows OS
↓ コマンドプロンプトでユーザから命令あったから、firstprogram.exe実行させよう。まずはmain()関数を呼びます。
main()関数(firstprogram.exe内)
↓ OSから呼ばれて、プログラム実行開始。まず1行目のprintf()関数呼びます。”立花アカネは、世界一の美少女デス♪¥n”を画面に表示しなさい。
printf()関数(stdioのどこか)
↓ 画面に表示しました。 ではリターンでmain()の次の行に帰ります。
main()関数(firstprogram.exe内)
↓ 2行目のreturn 0の場所に帰ってきました。じゃ、うちもリターン実行。これで終わり。
Windows OS
戻ってきました。このfirstprogramプログラムは、これで終了。
「――ま、こんな感じね」
「なるほど。ところで、return 0の最後の0の数字はなんです?」
「これは、無事に終了しましたよーって報告。1とかだと、異常な終了しました、マズいですってOSに報告するの。ま、お約束と覚えておいて」
だいたい、わかってきた。だが、俺はまだ腑に落ちない部分がある。
「先輩。あとわからないのは、mainの前後のintとか(void)とかの謎の文字だが」
「うん。まず、最初のintってのは、Integer、整数って意味。0とか1とか2とか100とか小数点の無い数字ね。0.5とかの小数点入ってる実数はintじゃなくて、floatとかdoubleとか使われるの」
「そのintがなぜ、ここに?」
「これは戻り値って言って、実はさっきのreturn 0の0の数字のことなの。関数が終了した時には、普通、戻り値が必要になるけど、それは、floatやdoubleじゃなくて、intの型、整数がここに返りますーってパソコンに教えているの。だから、プログラムの本文の中でも、returnの後ろが、0.5とかじゃなくて、0を返して合わせているでしょ?」
「はい」
「関数は、必ず入れる数値と戻り値があるの。このmain()の場合、リターンするときに、ここで0を返すってわけよ。その数字を呼び出した側のOSが見て、main()関数が成功したか問題あったか判断する材料にするの」
「戻り値の方はわかりました。じゃあ入れる方は?」
「これは、引数って言うけど、じつはこのプログラムには無いのでした。その時にはvoid、何も無し、をmainの後ろのカッコの中に書いておくのがCの文法の掟なのよ」
「ふーむ、つまりこのmain関数は、何も引数が無くて、intの数を返す関数ってことか。で、OSがこれを呼び出して、戻り値を見て成功したか判断する、と」
「じつはね、最初にvoid main(void)って書いておけば、戻り値も要らないの。二行目のreturn 0も必要なくなる。でも、それはOSへキチンと結果報告しない悪い書き方だし、-Wallオプション入れてたら、コンパイラからも警告されるわ」
「は、はあ……」
「あと、いずれは、mainで引数を受け取るヴァージョンも説明するわ。でも、今日は、これくらいにしておくわね」
ふと時計を見ると、もう帰る支度をする時間になっていた。
「あ! もうこんな時間か。先輩の話、密度が濃かったから、気付かなかったよ」
「ふふっ。明日は、もっと濃い話になると思うから、覚悟しておきなさいよ」
「うげっ」
俺は露骨に嫌な顔をする。先輩は、それを見てくすくすと笑った。