自己紹介
初めまして,竜崎と申します.
プログラミング言語を「完全に理解しています1」.
これから勉強を兼ねて色々と記事を書いていこうと思っています.
よろしくお願いします.
今回のテーマ
C言語初心者による,C言語初心者のための解説記事.
C言語の Hello, world! について理解したい.
C言語の Hello, world!
Hello, world! は,プログラミング言語に初めて触れる人や,新しいプログラミング言語を学ぶ人が最初に学ぶことの多い,「画面に文字列を表示させる」というプログラムです.
プログラミングでは,数値計算を行ったり,データベースに問い合わせたりと様々なことを行いますが,ほとんどの場合,その結果を何らかの形で画面上に表示させることとなります.よって,画面に文字列を表示させるプログラムは最初の一歩としてうってつけです.
とまあ御託はこの辺にして,本題に移りましょう.
今回はC言語の環境構築については割愛します.
C言語で Hello, world! を実現するには,以下のようなコードを記述します.今回は,この内容を hello.c という名前のファイルへ保存することにしましょう.
#include <stdio.h>
int main(void) {
printf("Hello, world!\n");
return 0;
}
【補足】他のプログラミング言語との比較
Hello, world! の構文は,プログラミング言語によって様々です.
例えば,Python だとよりシンプルに
print("Hello, world!")
と書けますし,逆に Java だと以下のように2 C よりも記述量が増える印象です.
class Hello {
public static void main(String[] args) {
System.out.println("Hello, world!");
}
}
hello.c を保存できたら,次はコンパイルと実行という2つの手順を踏みます.
コンパイル
まず,コンパイルについてです.hello.c に書いたプログラムは,そのままではコンピューターが読み取ることはできないので,コンピューターが読み取れる形式の実行ファイルに変換する必要があります.
実行ファイルが作られる過程では,プリプロセッサ,コンパイラ,アセンブラ,リンカの4つのソフトウェアが順に処理を行います.これについては以下のリンク先が詳しいです.
C言語の実行ファイル作成に使われることが多い GCC や clang といったツールは,4つの手順を一度にまとめて行うこともできるし,各手順を分けて行うこともできます.今回は分ける必要がないので,一度にまとめて行いましょう.
環境構築が無事に行われていれば,ターミナル(Windows の場合はコマンドプロンプトや PowerShell など)を開き,hello.c を保存したフォルダ(ディレクトリ)に移動してから,下のどちらかのコマンドを実行することができるはずです.
【GCC の場合】
gcc hello.c
【clang の場合】
clang hello.c
処理が正常に完了すれば,いずれの場合でも,Windows 環境では a.exe ,Mac/Linux 環境では a.out という実行ファイルが生成されているはずです.なお,-o オプションを使えば,生成される実行ファイルの名前を指定することもできます.
実行
コンパイルで実行ファイルができたら,ターミナルから次のプログラムを実行します.
【Windows の場合】
.\a.exe
【Mac/Linux の場合】
./a.out
どちらの場合でも,実行結果として
Hello, world!
と表示されるはずです.
hello.c の内容を紐解く
C言語の Hello, world! は,「意味がよく分からなくても動けばいいや」という「おまじない」として語られることもありますが,やはり意味をきちんと理解しておくのは大事だと思います.一つ一つ紐解いていきましょう.
printf() 関数と文字列
まず,Hello, world! と表示させる処理に直接関係するのは,hello.c の4行目,printf("Hello, world!\n"); の部分です.
printf() は,括弧の中身を表示させるという役割を担っています.printf() のように,括弧の中身を受け取り,受け取った中身に対して何らかの処理を行うプログラムを,C言語では関数といいます3.
次に,printf()の中身についてです.C言語では,複数の文字が連なった文字列を扱うときはダブルクォート " で囲みます.また,\n は改行を表す記号で,プログラム実行時,Hello, world! と表示された後きちんと改行するために必要となります.
また,C言語では,関数実行や,変数の宣言・代入などの命令を行う際,行末にセミコロン ; が必要です.
エントリーポイント
文字列を表示させる関数は printf() でしたが,C言語では printf("Hello, world!\n"); と1行書いて終わり,ではありません.C言語では,ソースコード中のどこかで必ず main 関数と呼ばれる関数を作り,実行したい処理を main 関数の中に入れる必要があります.
なぜ main 関数を作る必要があるかというと,C言語ではプログラムの最初に main 関数が実行されることが規約として決まっているからです.C言語における main 関数のように,プログラムで最初に実行される関数をエントリーポイントといいます.C言語のようにエントリーポイントが必要なプログラミング言語では,main もしくは Main という名前の関数がエントリーポイントになっていることが多いです.
C言語のエントリーポイントを定義するときの書式は,
int main(void) {
// ここに処理を記述する
return 0;
}
という形です.ここで,return 0; は,プログラムが正常に終了したことを表すために,整数 0 を実行結果として返すことを表します.また,関数が実行結果として整数を返すとき,関数名の前に int というキーワードを付ける必要があるので,main の前に int と書かれています.
main 関数の括弧の中身は void となっていますが,これは main 関数の括弧の中身が空であることを表します.
【補足】
この節の内容では,C99 というバージョンを仮定しています.
よって,C のバージョンによっては,
-
main関数の返り値型int -
main関数の引数の中身void -
main関数の返り値return 0;
が省略可能な場合もあります.詳細については本記事のコメント欄をご参照ください.
ヘッダファイルとディレクティブ
ここまでで,printf() 関数と main 関数に触れてきましたが,それらを組み合わせて以下のように書いても,まだ正しく動作しません4.
int main(void) {
printf("Hello, world!\n");
return 0;
}
// ↑ このままでは動かない!
コンパイラが知りたい main 関数はこれで定義できましたが,実は,main 関数の中で呼び出されている printf 関数について,この段階でコンパイラは何も知りません5.なので,printf 関数がどんなものかを定義しているファイルを別途読み込む必要があるわけです.
printf 関数は,stdio.h6というヘッダファイルのなかで宣言されています.stdio.h など,基本的な機能を提供するヘッダファイルは,C言語の環境構築をした段階で,コンパイラなどのツールと一緒に PC にダウンロードされています.
printf に限らず,既存の関数を呼び出すためには,その関数を定義しているヘッダファイルを事前に読み込む必要があります.ヘッダファイルをはじめ,ファイルを読み込むときには #include という命令を使用します.#include のように,# から始まる命令をディレクティブといいます.
ディレクティブは,コンパイルの前処理を行うプリプロセッサが読み取ります.#include の他には,ソースコード中の文字を単純に置き換えるマクロを定義するための #define や,マクロが定義されているかどうかで条件分岐を行う #ifdef などのディレクティブがあります.
まとめ
ここまでの内容から,改めて,C言語で Hello, world! を実現するための最終的なソースコードは以下のようになります.
#include <stdio.h>
int main(void) {
printf("Hello, world!\n");
return 0;
}
私自身,初めて見た時は呪文のように見えたソースコードですが,「おまじない」で終わらせず,一つ一つ順を追って理解していくのはやはり大切だなと思います.
謝辞
本記事の内容について,@SaitoAtsushi さん,@NyancoRitter さんより訂正のご指摘をいただきました。ありがとうございます m(_ _)m
以上,初投稿で拙い部分もあるかと思いますが,参考になれば幸いです.
最後までお読みいただき,ありがとうございました.X など各種 SNS を lit.link にまとめているので,もしよろしければフォローいただけると嬉しいです!
-
プログラマにはお馴染みの表現なのですが,プログラミング言語を少し触った段階で全てを分かった気になることを,俗に「完全に理解した」といいます.要は初心者だということです. ↩
-
【Java 経験者の方向け】ここではビルドツールなどは仮定せず,
javac Hello.javaでコンパイルしjava Helloで動かせる最小限の記述に留めているので,package宣言やクラスのアクセス修飾子は省いています.ご了承ください. ↩ -
プログラミング言語によってはメソッドと呼ばれることもあります. ↩
-
【追記】@SaitoAtsushi さんのコメントより.C89 ではヘッダファイルなしで
printf関数を呼び出せていたとのことです。ただ,C99 では削除されているとのことなので,ヘッダファイルなしで正しく動作する場面は限られると思います.https://qiita.com/drakosakron/items/0f795fe5560e3d7edf67#comment-5ede3e8240b7fd00154a ↩ ↩2 -
stdio.hの「stdio」は,standard input/output(標準入出力)の略です. ↩