2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【C】初めてのC言語(11. ヘッダファイル)

Posted at

はじめに

学習環境

  • 今回はpaiza.ioのC言語のエディタを使いました。

ヘッダファイルとは

概要

  • C言語のソースプログラムは「ソースファイル」「ヘッダーファイル」の2つで構成されています。
  • ソースファイルが肥大化した場合は複数のソースファイルに分割すると保守性が向上しますが、その場合は別ファイルに存在する関数などを利用できなくなってしまいます。
  • この時に個々の関数、オブジェクト、データ型などの宣言をして、別のソースファイルから利用できる状態にする(外部に公開する)のがヘッダファイルとなります。
    • おそらくこれ以外にもヘッダファイルを作るメリットがあるとは思いますが...

書き方のルール

  • ヘッダファイルが複数のソースファイルで読み込まれる(インクルードされる)と、重複定義となってコンパイルエラーになってしまいます。
  • そこでヘッダファイルを書く時は、以下のPoint.hのようにヘッダファイルの内容を「インクルードガード」というもので囲むことで安全にインクルードすることが出来ます。(※参考URL
  • インクルードガードを使うと、以下のように処理されるので重複定義とはならないそうです。
    • 最初にPoint.hをインクルードした時は、その内容が全てインクルードされる。
    • 2回以上Point.hをインクルードした時は、その内容はインクルードされない(バイパスされる)。
  • こちらの記事だと、インクルードガードを#ifndef ... #define ... ~ #endifではなく、#pragma onceと一行で表現できる書き方が紹介されていました。
    • ただし#pragma onceは使えない環境があるらしいので、今回は#ifndef ... #define ... ~ #endifを採用しました。
  • また、ヘッダファイル中で「構造体の型の定義」や「関数のプロトタイプ宣言」などはできても、「グローバル変数の定義」と「関数そのものの定義」はNGだそうです。
  • 加えて、標準ヘッダファイル名を再利用しないというルールもあるため、命名の際には注意が必要です。
Point.h
#ifndef POINT_H
#define POINT_H

...    // Point.hの内容を記述する。

#endif // POINT_H

サンプルコード

  • 上記の「ヘッダファイルの書き方のルール」を踏まえて、以下のコードを作成しました。
    • 位置に関わる処理をまとめたPoint.c
    • 位置を表現する構造体の定義と、位置に関わる処理のプロトタイプ宣言をまとめたPoint.h
  • 短いコードですが、処理をグルーピングして別のファイル(.c)にまとめることで、少しコードがスッキリした気がします(※個人の感想です)
Main.c
#include <stdio.h>
#include "Point.h"

int main(void){
    Point p = { .x = 2, .y = 3 };
    printLocation(&p);
    
    // 位置をずらす。
    move(&p, 3, 5);
    printLocation(&p);
}
Point.h
#ifndef POINT_H
#define POINT_H

// 構造体:位置型
typedef struct Point {
    int x;    // X座標
    int y;    // Y座標
} Point;

// [プロトタイプ宣言]位置を標準出力する。
void printLocation(Point*);

// [プロトタイプ宣言]指定した座標に移動させる。
void move(Point*, int, int);

#endif // POINT_H
Point.c
#include <stdio.h>
#include "Point.h"

// 位置を標準出力する。
void printLocation(Point* point) {
    printf("X座標は%d、Y座標は%dです。\n", point->x, point->y);
}

// 指定した座標に移動させる。
void move(Point* point, int x, int y) {
    point->x = x;
    point->y = y;
}
実行結果
X座標は2、Y座標は3です。
X座標は3、Y座標は5です。

参考URL

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?