最初のCプログラムを解説

前回の授業ではGCCコンパイラをインストールし、一番簡単なhello worldサンプルを作成しました。今回の授業ではこのサンプルを解説していきます。まずコードは下記の通りです。

#include <stdio.h>

int main()
{
    printf("hello, world\n");
    return 0;
}
Code language: Arduino (arduino)

コードは非常にシンプルで、1行の文字を出力するだけの機能です。

次に上から下へ、1行ずつコードを解析します。

1. #include <stdio.h>

前回の授業でプリプロセスについて簡単に触れましたが、この最初のコードがプリプロセス命令です。どこから判断するか?先頭の#記号が目印です。

#:プリプロセス命令のマーカー。プリプロセッサに渡して処理され、コンパイルの最初の工程で実行されます。

include:ヘッダーファイルを読み込むキーワード。指定したファイル内のコードを現在のプログラムにコピーする役割があります。

<stdio.h>:標準入出力ヘッダーファイル(standard input output)。画面への出力、キーボードからの入力など入出力関数がまとめて定義されており、下で使用するprintf関数はこのファイル内に定義されています。

厳密に言うとプリプロセスはC言語自体の文法に含まれません。C言語のプリプロセスはC言語のコア文法の一部ではない、コンパイラが本コンパイルの前に独立して実行する工程です。コンパイル全体の流れの一部ですが、C言語本来の文法・意味体系に属さない処理となります。

簡単に説明すると、独立したプリプロセスプログラムが文字置換を実行します。例えば#include <stdio.h>はstdio.hの中身すべてをこの行にコピーし、元の1行ごと置き換えます。仮にstdio.hの内容がAAAAAAAAAだったとします。

するとコンパイラに渡される段階で、コードは以下のようになります。

 AAAAAAAAA

int main()
{
    printf("hello, world\n");
    return 0;
}
Code language: Arduino (arduino)

もちろんこれは仮の話で、実際のヘッダーファイルは複雑な内容になっています。興味のある方は実際にファイルを開いて確認してみてください。

このヘッダーファイルはPC内に保存されており、OSによって保存パスが異なります。

Linux/Unixシステム:通常 /usr/include/stdio.h に配置

Windows (Visual Studio):VC/include/stdio.h に配置

macOS (Xcode):/Applications/Xcode.app/.../usr/include/stdio.h に配置

各自PC内のファイル検索ツールで、実際の配置場所を探してみましょう。

これでプリコンパイルについて基礎的な理解ができたでしょうか?

もし#include <stdio.h>の行を削除すると、コンパイラはprintfを認識できずエラーを出力します。実際にこの行を消し、gccでコンパイルして動作を確認してみてください。

ヘッダーファイルを削除した状態

再度コンパイルを実行するとエラーメッセージが表示されます

2. int main()

main = C言語のプログラムエントリーポイント関数

  1. どんなCプログラムも実行時、OSが自動的にmain関数から処理を開始します。プログラムにはmainが一つだけ存在しなければならない
  2. int:関数の戻り値型を表し、整数(integer)を意味します。
  3. ():これが関数であることを示す記号。括弧内に引数を記述可能、空括弧は引数なしを意味します。

このmainの記法は後世の多くのプログラミング言語に継承されています。exeファイルをダブルクリックする、またはコマンドラインから実行コマンド(helloなど)を打つと、OSが自動的にmain関数を呼び出してプログラムが起動します。

先頭のintは関数の戻り値型で、今後自作関数を定義する際にすべて記載する必要があります。後の講義で詳しく解説します。

丸括弧()は関数が受け取る引数の型を宣言する箇所です。今回は空なので引数を受け取らない設定です。引数を受け取る書き方は以下の通りです。

int main(int argc, char *argv[])Code language: CSS (css)

こちらはint型と文字列配列の2つの引数を受け取る記法で、詳細は後の授業で説明します。

main関数の引数はOSから渡されます。ではこの引数はどこから取得されるのでしょう?

コマンドラインツールのpingコマンドを使ったことがある方も多いでしょう。例えばping 12.36.4.xxxで通信確認をする場合、pingがping.exeプログラム、後ろのIPアドレス12.36.4.xxxがping.exeのmainに渡される引数となります。

同様にhelloプログラムをコマンドラインでhello abcと実行した場合、abcが引数として渡されます。main後ろの丸括弧内の変数は、このようにユーザーが入力しOSから転送された値を受け取る役割です。

まとめて覚えておきましょう:mainはプログラム唯一の実行開始点、1つだけ定義しOSによって呼び出され、コマンドライン入力の値はOS経由でmainに渡されます。

3. { } 波括弧

関数本体の境界を定義します。{が関数処理開始、}が終了を表し、関数内の全コードを2つの括弧の間に記述します。

4. printf("hello, world\n");

  • printf:print formatの略、フォーマット出力関数。コンソールに文字を出力する機能です。
  • 二重引用符" "文字列定数を囲む記号、中に出力したいテキストを記載します。
  • \n:エスケープシーケンス、改行文字。文字出力後自動的に次の行へ移動します。
  • ;:C言語の文終了マーカー。実行可能な1文ごと末尾に記述しないとコンパイルエラーが発生します。

関数名末尾のfはフォーマット出力を意味し、後の講義で深く解説します。今は単純に「hello, world\nという文字をコンソールに表示し、\nで自動改行する」と理解してください。

5. return 0;

  • returnmain関数に整数を返却し、現在実行中の関数を終了させます。なぜreturnが必要か?mainの先頭にintと戻り値型を宣言しているため、関数内で整数を返す必要があるからです。
  • 0:業界共通の規約で、プログラムが正常にエラーなく終了したことを意味し、OSに実行結果を通知します。
    • 0を返却 = プログラム正常終了
    • 0以外の数字(例:return 1;)= プログラム異常終了

最新のC規格ではmain末尾のreturn 0;を省略可能で、コンパイラが自動補完します。ただ初心者は規則通り記載することを推奨します。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です