- 第２章　Hello, Worldプログラムを理解する

- 2.1　printf関数

- 2.1.1　関数呼び出し式

- 2.1.2　文字列リテラル

- 2.1.3　セミコロン

- 2.1.4　インデント

- 2.2　#include <stdio.h>

- 2.3　main関数

- 2.4　空白文字

- 2.5　注釈

- 2.5.1　// による注釈

- 2.5.2　/* */ による注釈

- 2.5.3　注釈に何を書くか

- 2.6　練習問題

第２章　Hello, Worldプログラムを理解する

無事に「Hello, World」と表示させることができたでしょうか？ この章では、Hello, World プログラムの内容を細かく説明してみたいと思います。

ここでもう１度、Hello, World プログラムを再掲しておきます。

#include <stdio.h>

int main(void)
{
printf("Hello, World\n");
return 0;
}

Hello, World

2.1　printf関数

Hello, Worldプログラムを眺めてみると、「Hello, World」と書かれている部分があることが分かると思います。

printf("Hello, World\n");

実行結果も「Hello, World」ですから、どうやらこの辺りが、このプログラムの肝になっていそうです。

最初の部分、「printf」というのは、Ｃ言語が持っている機能の１つで、正式には printf関数と呼ばれています。 声に出して読むときには「プリントエフカンスウ」と発音します。 printf関数を使うと、「画面に好きなメッセージを表示する」ことができます。

関数という用語については、第９章で改めて取り上げますが、 今のところは、何らかの仕事をこなすために必要なプログラムを、 １つにまとめたものだとイメージして下さい。 printf関数にとって仕事とは、「画面に好きなメッセージを表示する」ことです。

なお、プログラムを実行して、何らかの結果を表示したり、書き出したりすることを、出力と言います。 そのため、printf関数は「画面に好きなメッセージを出力する」ための関数だということになります。

また、関数を使うことを、「関数を呼び出す」と言います。 そのため、「printf関数を使う」という表現は、「printf関数を呼び出す」と言い換えられます。

printf関数は、「画面に好きなメッセージを出力する」と書きましたが、実は画面であるとは限りません。 正確に言えば、printf関数は、標準出力という場所へ出力を行います（場所っぽくない名前ですが、そういうものです）。 標準出力が具体的には何なのかは、プログラムを実行する環境によって異なる可能性がありますし、 変更することもできますが、ほとんどの環境では、画面のことです。

2.1.1　関数呼び出し式

「printf」の直後には、開き括弧「(」があります。 そして、これに対応するらしき、閉じ括弧「)」が後ろの方にあります。

これらの括弧は、printf だから付いているというよりは、printf が関数だから付いているものです。 括弧の内側には、関数がその仕事（printf関数であれば、「画面に出力すること」）をこなすために必要な情報を記入します。

このような、

関数の名前(必要な情報)

という記述は、関数呼び出し式と呼ばれていて、その名の通り、関数を呼び出すための構文です。 今後、printf関数以外の関数も登場することがありますが、いつもこの構文で呼び出しを行うことができます。

なお、関数を呼び出すときに指定する情報のことを、実引数（じつひきすう）と呼びます。 また、実引数を指定することを、実引数を渡すと表現することがあります。

2.1.2　文字列リテラル

printf関数を呼び出すとき、どのように実引数を渡しているかに注目してみましょう。

printf(Hello, World);

というような記述ではなく、

printf("Hello, World\n");

となっており、色々と余計なものが付いているようです。

まず、ダブルクォーテーション（二重引用符）で囲まれています。 このように、文字の並びを "" で囲んだものを、文字列リテラルと呼びます。 文字列リテラルは、命令ではなく、データであることを表しています。 つまり、「Hello, World」という命令が存在する訳ではなく、printf関数に渡すデータ（情報）であるという意味です。

また、「\n」という謎の２文字が含まれています。 これは、「この位置で改行して欲しい」ということを表す特別な表記です。

１行分のデータを出力し終えたら、次に何かを出力する人のために、改行しておくと考えて下さい。 そうしないと、次に何かを出力するとき、前の行の続きから始まってしまいます。

ところで、"Hello, World" ではなく、"こんにちは" のような日本語は出力できないかと思うかも知れません。 できないことは無いのですが、日本語はうまく出力できないケースがあり、話が難しくなりがちなので、 入門段階では避けることが多いです。本書でも避けておきます。

2.1.3　セミコロン

よく見ると、行末にセミコロン(;) があります。 これは、１つの文の終わりを示していて、日本語で文章の終わりに付ける句点（。）に当たるものです。 Ｃ言語では、このように明確に文の終わりを示さないといけません。

セミコロンを付けなくてはならない箇所と、付けてはならない箇所があって分かりづらいですが、 これはほぼ慣れの問題です。もし間違っていたら、ほとんどの場合、コンパイルに失敗します。

2.1.4　インデント

printf関数を呼び出している行は、先頭部分に空白があります。

printf("Hello, World\n");

このように、行の先頭部分に空白を入れることを、インデント（字下げ）と呼びます。空白には、半角の空白文字か、タブ文字を使います。

これは単に読みやすさのために行うものであって、自由にして構いませんが、一般的に { } の内側ではインデントを行います。

これまた "一般的には" ということですが、インデントに空白文字を使うなら 2、4、8文字のいずれかにすることが多いです。タブ文字を使うのなら１つだけ入れます。本書では、空白 4文字にしています。

2.2　#include <stdio.h>

Hello, Worldプログラムの先頭には、次のような行があります。

#include <stdio.h>

これは、「シャープインクルード　スタンダードアイオードットエイチ」と読みます。 なぜか、stdio を「スタジオ」と読んでしまう人がいるようですが違います（スタジオは studio です）。

この行の意味は、「stdio.h の内容を、この位置（この行）に組み込んでくれ」ということです。 stdio.h はファイルの名前ですが、そのファイルに書かれている内容をそっくりそのまま、 この行に上書きコピーするイメージです。 なお、stdio.h は、コンパイラをインストールしたときに、PC内のどこかに作られています。 オンラインコンパイラの場合は、その Webサイトの側に存在しているはずです。

stdio.h の「std」は「standard」の略で「標準的」という意味、 「io」は「input output」つまり「入力、出力」のことです。 つまり stdio.h は、「標準的な入力と出力の機能を集めたもの」だということです。

この１文が必要である理由は、stdio.h の中に printf関数に関するプログラムが書かれているからです。Hello, Worldプログラムは printf関数を使うので、最初に組み込んでおくという訳です。

printf関数と同じことをするプログラムを自力で開発することは、ものすごく大変です。誰しもが使う一般的な機能なので、あらかじめ用意されていて、必要なときに「#include <stdio.h>」と書いてやるだけで使える仕組みになっているのです。

2.3　main関数

次に、以下の行に注目してみましょう。

int main(void)

これは、main関数（メインかんすう）というもので、プログラムの実行はここからスタートします。 実際には、{ と } も main関数を構成している一部なので、

int main(void)
{
ここに処理が書かれている
}

ここまでが１セットになります。 「int」と「void」については、今のところそれほど関係しないので、ここでは触れません。 第９章で、改めて取り上げたいと思います。

プログラムを実行すると、main関数を構成する { の直後の部分から始まり、上から下へ向かって処理が行われていきます。 Hello, Worldプログラムの場合、{ の直後には printf関数の呼び出しが書かれていますから、 画面に「Hello, World」と出力されます。 もし、プログラムが次のようになっていたら、printf関数が、書かれている順番通りに２回呼び出される訳です。

#include <stdio.h>

int main(void)
{
printf("Hello,\n");
printf("World\n");
return 0;
}

Hello,
World

main関数の終わりの部分には、

return 0;

という１文があります。 これは、return文と呼ばれるもので、関数の処理を終えることを意味しています。 ここで、main関数の処理は終了するので、return文よりも後ろに処理を書いても無意味です。

「return」の後ろについている「0」の意味の説明を含めて、 return文に関する話題は、第９章で再び取り上げることにします。

2.4　空白文字

１つの単語の途中のような一部の例外を除いて、空白を入れることは自由です。空白は、半角の空白文字か、タブ(Tab) で入れます。

例えば、

printf( "Hello, World" );

このように、( ) の内側に空白を空ける書き方を好む人もいます。 一方で、次の書き方はエラーになります。

print f("Hello, World");

これは「printf」という１つの単語の途中だからです。 単語の途中に空白が紛れ込んでいると、もはや別の言葉になってしまいます。

2.5　注釈

ここまで、一気に色々なことを学んできたため、 もしかすると、プログラムにメモを入れておきたいと考えた人もいるかも知れません。 まさにそういった用途に使える、注釈（コメント）という機能があります。

例えば、次のように使うことができます。

/*
Hello, Worldプログラム
*/
#include <stdio.h>

int main(void)
{
printf("Hello, World\n");  // "" で囲まれた文字の並びを出力。\n は改行のこと
return 0;
}

Hello, World

注釈には２つの形式がありますが、いずれにしても、注釈の部分はコンパイルの際に無視されます。 無視してくれるので、そこに何が書いてあっても影響しない。つまり、好きにメモを書いておけるという訳です。

2.5.1　// による注釈

「//」を使うと、そこから行の終わりまでが注釈になります。

ただし、文字列リテラルの内側に入れた場合、 それは文字としての「/」が２つ並んでいると認識されるだけで、注釈にはなりません。

#include <stdio.h>

int main(void)
{
printf("Hello, //World\n");

return 0;
}

Hello, //World

2.5.2　/* */ による注釈

「/*」と「*/」をペアで使うと、その間がまとめて注釈になります。 こちらの方法は、複数行をまとめて注釈にできる他、 行の一部分だけを注釈にすることができます。

こちらの方法も、文字列リテラルに入れた場合は、ただの文字と認識されます。

#include <stdio.h>

int main(void)
{
printf("Hello, /*World*/\n");

return 0;
}

Hello, /*World*/

「/*」「*/」の方が自由度は高いですが、閉じる方を書くことが意外と面倒臭いため、 「//」の方が好まれることが多いように思います。

2.5.3　注釈に何を書くか

注釈は、実戦的な開発では、的確な使い方が求められますが、 学習段階としては、思ったことを素直にメモとして残していけばいいでしょう。

例えば、printf関数が出力を行っているだとか、 main関数のところからプログラムの実行が始まるだとかといったことは、 Ｃ言語を理解していれば当たり前のことなので、実戦の場では書くべきではありません。 情報がたくさんあると、かえって邪魔になってしまうことがあるので、 他の人の役に立つ情報を選んで、書き残すようにします。

2.6　練習問題

この章から、章の終わりに練習問題を載せておきますので、取り組んでみて下さい。 解答は、問題の後にあります。

問題①　出力するメッセージの変更

Hello, Worldプログラムを修正して、「Good Morning!!」と出力するようにして下さい。

問題②　改行

次のプログラムを実行すると、どのような出力結果になりますか？

#include <stdio.h>

int main(void)
{
printf("Hello,\nWorld\n");
return 0;
}

問題③　セミコロン

printf関数を呼び出すとき、行末のセミコロンが無かったらどうなりますか？

問題④　main関数

main関数の「main」の部分を、「Main」のような別の表記に変えたらどうなりますか？

問題⑤　return文

次のプログラムを実行すると、どのような結果になりますか？

#include <stdio.h>

int main(void)
{
return 0;
printf("Hello, World\n");
}

練習問題の解答

問題①　出力するメッセージの変更

printf関数に渡す実引数を変更すれば良いです。

#include <stdio.h>

int main(void)
{
printf("Good Morning!!\n");
return 0;
}

Good Morning!!

問題②　改行

改行の指示を与える \n は、どの位置に入れてもいいですし、２個以上使うこともできます。 「Hello,」の直後と、「World」の直後で改行されるので、次のような結果になります。

Hello,
World

問題③　セミコロン

文の区切りとしてセミコロンは必須です。 もし書き忘れると、その後ろに続いているコードと一体化して扱われてしまい、 大抵は構文がおかしくなるため、コンパイルに失敗して、エラーになります。

問題④　main関数

main関数は、プログラムの開始位置を示すという重大な役割を持っているため、 必ず、この名前の通りに存在していなければなりません。 少しでも名前を変えたら、コンパイルに失敗して、エラーになります。

問題⑤　return文

プログラムの実行は main関数から開始され、{ } の中を、上から下へ向かって進みます。

このプログラムでは、最初に登場する処理が return文になっています。 return文は、関数の処理を終えるためのものなので、この時点で main関数が終了してしまい、 後続の printf関数は呼び出されません。 従って、実行結果は、以下のように、何も出力されません。