Creating and Running .c Files
Cのコードをテキストファイルに保存し、コンパイルして実行する方法を解説します。ファイルの実体はただのテキストファイルで、拡張子を『.c』にしたものです。関数の宣言をまとめるヘッダーファイルは拡張子を『.h』にします。
.cファイルの書き方
テキストエディタで C のコードを記述し、ファイル名を『.c』拡張子で保存します。ファイルの文字コードは『UTF-8』で保存してください。
greet.c
#include <stdio.h>
int main(void) {
char name[] = "太郎";
int age = 25;
printf("こんにちは、%sさん!\n", name);
printf("年齢: %d歳\n", age);
if (age >= 20) {
printf("成人です。\n");
} else {
printf("未成年です。\n");
}
return 0;
}
1行目の『#include <stdio.h>』は標準入出力ライブラリを取り込む宣言です。『printf』を使うために必要です。プログラムの開始点となる『main』関数から処理が始まります。
コメントの書き方
.c ファイルにはコメント(メモ)を記述できます。コメントはコンパイラに無視されるため、コードの説明や注意書きを残すのに使います。
| 書き方 | 説明 |
|---|---|
| // コメント | 1行コメントです。『//』の後にスペースを1つ入れて記述します。C99以降で使用できます。行末まで有効です。 |
| /* コメント */ | 複数行コメントです。『/*』から『*/』までの範囲がコメントになります。C89から使用できます。 |
sample_comments.c
#include <stdio.h>
/*
以下はメイン関数です。
プログラムの開始点になります。
*/
int main(void) {
// ユーザー名を設定します。
char name[] = "花子";
// 挨拶メッセージを表示します。
printf("こんにちは、%sさん!\n", name);
return 0;
}
現代の C 開発では1行コメント(『//』)が広く使われています。古い環境との互換性が必要な場合は『/* */』を使います。
ヘッダーファイル(.h)の書き方
ヘッダーファイルは関数の宣言や定数の定義をまとめるファイルで、拡張子を『.h』にします。『#include』を使って .c ファイルから読み込みます。ヘッダーファイルの実体もただのテキストファイルです。
ヘッダーファイルには『インクルードガード』と呼ばれる記述を入れるのが一般的で、インクルードガードを一言で説明すると「同じファイルを重複して『#include』しても問題なくコンパイルが通るようにする」といったものになります。管理人の経験則になりますがインクルードガード周りは慣れていないとかなり複雑で、それ故にC言語の習得に挫折してしまう大きな理由のひとつになっているはずですので、このあたりを細かく見ていきましょう。
まず以下の表でインクルードガードの記法を確認してください。以下はヘッダーファイルが『greeting.h』だった場合の記述となります。その中の『GREETING_H』といった部分についてですが、ファイル名を大文字にしたもの(『greeting.h』→『GREETING_H』)を使うのが慣習となっています。これは名前が他のヘッダーファイルと重複しなければ問題ないので自由に設定することも可能ですが、特に理由がなければ慣習通りに組むと良いでしょう。そうすることでソースコードを見ただけで『GREETING_H』→『greeting.h』と該当ファイルを絞り込むことが可能になります。
| 記述 | 略語の由来 | 意味 |
|---|---|---|
| #ifndef GREETING_H | if not defined(もし定義されていなければ) | 『GREETING_H』がまだ定義されていなければ、この記述から『#endif』までを読み込みます。これは要するに一種のif文です。 |
| #define GREETING_H | define(定義する) | 『GREETING_H』を定義します。『#define』は基本どこに書いても動作しますが、『#include』の重複エラーを避けたいといった場合は『#ifndef』の直下に記述するのがお決まりのパターンとなっています。 |
| #endif | end if(もし〜の終わり) | 『#ifndef』の範囲を閉じます。 |
では最初にインクルードガードを書かずに、同じヘッダーファイルを2回読み込むとどうなるか見てみましょう。使用ファイルは『greeting.h』と『main.c』です。
greeting.h(インクルードガードなし)
// 挨拶メッセージを定義します。
typedef struct {
char name[50];
int age;
} Person;
main.c
#include <stdio.h>
#include "greeting.h"
#include "greeting.h" // 2回目の読み込み
int main(void) {
Person p = {"太郎", 25};
printf("%s(%d歳)\n", p.name, p.age);
return 0;
}
これをコンパイルするとエラーになります。
gcc main.c -o main main.c:3:10: error: redefinition of 'Person'
2回目の『#include "greeting.h"』で『Person』の定義が重複し、「すでに定義されています」というエラーが発生していますね。小さなプログラムでは同じファイルを2回『#include』してしまうことはまずありませんが、大きなプログラムになればなるほどそういったミスをしてしまいがちになります。では同じヘッダーファイルにインクルードガードを追加してみましょう。
greeting.h(インクルードガードあり)
#ifndef GREETING_H
#define GREETING_H
// 挨拶メッセージを定義します。
typedef struct {
char name[50];
int age;
} Person;
#endif
main.c
#include <stdio.h>
#include "greeting.h" // 1回目: GREETING_H が未定義 → 読み込まれる → GREETING_H が定義される
#include "greeting.h" // 2回目: GREETING_H が定義済み → 無視される
int main(void) {
Person p = {"太郎", 25};
printf("%s(%d歳)\n", p.name, p.age);
return 0;
}
今度はコンパイルが成功します。
gcc main.c -o main ./main 太郎(25歳)
2回目の『#include "greeting.h"』では、1回目で『GREETING_H』が定義済みになっているため、『#ifndef GREETING_H』の条件を満たさず、中身がすべて無視されます。これがインクルードガードの効果となり、重複エラーが回避できています。繰り返しになりますが、大きなプログラムになればなるほど重複して読み込ませてしまうというミスが発生しがちですので、特別な理由がない限りはインクルードガードを必ず入れるようにした方が良いでしょう。
続いてヘッダーファイルの実践例を見ていきましょう。まず以下の表で『#include』の記法を確認してください。標準ライブラリのヘッダーは『< >』で囲み、自分で作成したヘッダーは『" "』で囲みます。
| 書き方 | 説明 |
|---|---|
| #include <stdio.h> | 標準ライブラリのヘッダーを読み込みます。コンパイラが管理するディレクトリから検索します。 |
| #include "calc.h" | 自作のヘッダーを読み込みます。現在のディレクトリから検索します。 |
では実際にファイルを分離してみましょう。ヘッダーファイル『calc.h』には関数のプロトタイプ宣言(「こういう関数がありますよ」という宣言)を書き、ソースファイル『calc.c』には関数の中身(実際の処理)を書きます。そして『main.c』から『calc.h』を『#include』して関数を呼び出します。
calc.h
#ifndef CALC_H #define CALC_H // 足し算を行います。 int add(int a, int b); // 引き算を行います。 int subtract(int a, int b); #endif
calc.c
#include "calc.h"
int add(int a, int b) {
return a + b;
}
int subtract(int a, int b) {
return a - b;
}
main.c
#include <stdio.h>
#include "calc.h"
int main(void) {
printf("3 + 5 = %d\n", add(3, 5));
printf("10 - 4 = %d\n", subtract(10, 4));
return 0;
}
複数のファイルに分かれている場合は、コンパイル時にすべての .c ファイルを指定する必要がありますのでご注意ください。例えば今回のサンプルですと、以下のような記述になります。
gcc main.c calc.c -o calc_app
コンパイル時のそれぞれの意味や注意点等は以下の表を確認してください。
| 部分 | 意味 |
|---|---|
| gcc | Cコンパイラを起動します。 |
| main.c calc.c | コンパイルする .c ファイルをすべて指定します。指定する順序は自由です。.h ファイルは『#include』で自動的に読み込まれるため指定不要です。 |
| -o calc_app | 出力する実行ファイルの名前を指定します。省略すると『a.out』になります。 |
そしたら出来上がったファイルを実行させればOKです。
./calc_app 3 + 5 = 8 10 - 4 = 6
Overview
.c ファイルはただのテキストファイルです。テキストエディタで C のコードを書き、拡張子を『.c』にして保存するだけで作成できます。特別なツールは必要ありません。
C はコンパイル型言語のため、『gcc ファイル名.c -o 出力名』でコンパイルし、『./出力名』で実行するという2ステップが必要です。コンパイルによって機械語の実行ファイルが生成されるため、実行速度が速いのが特徴です。
コメントは1行コメント(『//』、C99以降)と複数行コメント(『/* */』)の2種類があります。現代の C 開発では1行コメントが広く使われています。
関数の宣言をまとめるヘッダーファイル(.h)を使うことで、プログラムを複数のファイルに分割して管理できます。ヘッダーファイルには『#ifndef』『#define』『#endif』によるインクルードガードを入れることで、重複読み込みによるコンパイルエラーを防ぐことができます。
macOS では『xcode-select --install』を実行するだけで gcc が使えるようになります。gcc のインストールについては『環境構築』を参照してください。
If you find any errors or copyright issues, please contact us.