2012/06/11

C言語 複数ファイルをコンパイル

プログラムの規模が大きくなってくると、機能ごとにファイルに分けたほうがよい。そうすることで管理、再利用などがしやすくなる。複数ファイルのコンパイル方法は、拡張子が「.h」のヘッダファイルによって関連付けることで実現する。以下は3つのソースファイルと、ひとつのヘッダファイルで構成されている。内容的には10進数を入力すると、2進数と16進数に変換して表示するプログラム。各進数ごとにファイルを分けてみた。

main関数があるファイル main.c

/* main.c */
#include <stdio.h>
#include "nbase.h"
int main(void){
    int num;
    char str[10], buf[512];
    printf("Decimal Number: ");
    setbuf(stdout,buf);
    fgets(str,10,stdin);
    fflush(stdout);
    /* 文字から整数へ変換 */
    num = atoi(str);
    /* Binary Number */
    binNum(num);
    /* Hexadecimal Number */
    hexNum(num);

    return 0;
}
atoi関数は文字列を数字に変換する。このプログラムは整数入力前提だが、文字が入力されると手前まで有効となる。文字のみだと0として扱う。2進数と16進数の表示は以下の別ファイルの関数に投げている。

2進数変換 bin.c

/* bin.c */
#include <stdio.h>
void binNum(int num){
  int i,j;
  int barray[64];
  int binary;
  printf("%s","Binary Number: ");
  if(num == 0){
     printf("%d\n",num);
  }else{
     for(i=0; num>0; i++){
         binary = num % 2;
         barray[i] = binary;
         num = num / 2;
     }
     for(j=i-1; j>=0; j--){
         printf("%d", barray[j]);
     }
     printf("\n");
  }
  return;
}
C言語では2進数の表示は標準で備わっていないので、自分で作ってみた。プログラムとしては、あまりよろしくない感じがする。もう少し簡潔にしたいところだが、普通どうやっているのだろうか。暇なときに調べてみよう。

16進数変換 hex.c

/* hex.c */
#include <stdio.h>
void hexNum(int num){
    printf("Hexadecimal Number: 0x%x\n",num);
    return;
}
わざわざ別にする必要もない内容だが、ファイルを分けるというテーマの便宜上、分けてみた。

ヘッダファイル nbase.h

/* nbase.h */
#ifndef NBASE_H
#define NBASE_H

/*ヘッダファイルにはプロトタイプ宣言だけ行う*/
void binNum(int num);
void hexNum(int num);

#endif
mainと関連付けたい関数のプロトタイプ宣言だけ行っている。ここにグローバル変数やstatic関数を宣言するとおかしくなるので書かない。#ifndef、#define、#endifは重複定義を避けるために入れている。これをインクルードガードという。C++の書き方だが、Cでも有効なので入れてみた。

コンパイル方法

gcc main.c bin.c hex.c nbase.h
各ソースファイルとヘッダファイルを並べてコンパイルすることで、ひとつにまとめた exeファイルを作ることができる。
実行して255と入力すると以下のような結果になる。
Decimal Number: 255
Binary Number: 11111111
Hexadecimal Number: 0xff


C言語 ANSI C89 Meadow & MinGW GCC 目次