• ベストアンサー

複数ファイルに分割した時の構成について

大学の卒論にむけてプログラムを書いていて、一つのmain.cでは長くなってきたので、関数を func1.h func1.c のような別ファイルに記述することにしました。 その現在の構成を、質問欄の下部に簡単に書いたので、構成が自然かどうか意見をお聞きしたいです。特に、 「include文、define文をヘッダファイルにまとめて、各ファイルからincludeしている構造」がコードの記述方法として、きもちわるくないか、一般的かどうか、教えてください。 このようにした理由は、 ・defineマクロを多くのサブ関数で利用している。 ・define定義の値を細かく変えながら実行し、結果の違いを出力したい。 ・その為、各ファイルの頭にdefine定義を置いた場合、定義の値を  いちいち全てのファイルで変更しなければならなくなり、面倒…。 →defineマクロをdefine.hにまとめた。ついでに、<stdio.h>,<math.h>なども置いてしまえばスッキリするかも~。 という経緯です。 理学の学科でまわりに詳しい人がいなく、 プログラム知識もほぼ独学なので、不安に感じて質問しました。 よろしくおねがいします。 +++++++++++++ 以下が、簡単なファイル構成です +++++++++++++ -----define.h----- #include <stdio.h> #include <math.h> #define A_MAX 3 #define B_MAX 5 -----main.c---- #include "define.h" int main() { func1(); func2(); func3(); } -----func1.h---- #include "define.h" void func1(int hoge); //プロトタイプ宣言 -----func1.c---- #include "func1.h" void func1() { hogehoge; } ------func2以下、func1と同構造

  • minoa_
  • お礼率79% (126/158)

質問者が選んだベストアンサー

  • ベストアンサー
  • goosyu
  • ベストアンサー率58% (36/62)
回答No.2

 このようなヘッダファイルの作成には色々な考え方があるので,一般的な回答は難しいのであくまでも1つの経験的な意見としてお聞きください。  プログラム共通でdefineを使いまわすということであれば,1つのヘッダファイルを作るのは問題ありません。  「define.h」はdefineをまとめて管理するファイルとして定義した場合,共通のヘッダをインクルードするのは矛盾を感じます。ヘッダファイルから元のヘッダファイルとは関係性が低いヘッダファイルをインクルードを行うと,もとのヘッダファイルの定義または意味がぼやけてしまいます。結果的に新しい関数を追加する際に「define.h」の内容を確認しないとCソースファイルに新しくインクルードが必要か判断しないといけなくなります。見た目は「スッキリ」するかもしれません,他人には読みにくいソースコードになります。  また,共通のdefineが必要であっても必ずしも「stdio.h」または「math.h」をインクルードする必要はない場合も考えられ,結果的には無駄なインクルードとなります。無駄なインクルードはコンパイル時間が余計にかかるので小規模の開発では影響が少ないですが,よいことはありません。  開発規模が大きくなるとソースファイルをすべてコンパイルすると数時間というケースがあります。この問題を解決するためには修正したファイルだけをコンパイルして作業効率をあげます。修正したファイルが共通ヘッダファイルであれば,ほぼ全ソースコンパイルとなり効率が悪くなります。この為,変更が考えられるヘッダファイルをまとめることはあまりせず,Cソースコードから必要なヘッダファイルをインクルードさせることが多いです。

minoa_
質問者

お礼

なるほど、勉強になります。 後輩が見ても分かりやすいようにしたいのでその辺も考え、 ご意見を参考にしてファイル構成を修正したいと思います。 ありがとうございました~。

その他の回答 (5)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.6

#4 ではインクルードガードを define.h に入れるとありますが, func1.h~func3.h にも入れておくべきでしょう. あと, 「define定義の値を細かく変えながら実行し、結果の違いを出力したい。」というなら本当は #define で与えるのではなく, プログラム実行時に引数として値を与えるべきだと思います.

minoa_
質問者

お礼

お返事遅れてすみません。 その値によってデータの数が変わるので、 配列の大きさを変えるためDEFINEを使っていましたが、 仰る通りだと思い、DEFINE定義の大部分を引数に変えました。 配列長のDEFINE定義は残したためdefine.hは結局残りましたが、 意見は参考になりました。 ありがとうございました~。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.5

空白を含めて全く同じものへの #define だからエラーなどにはならないはずだが.... さておき, main.c で func1.h を #include しないのはなぜ? 「使う前に宣言する」のでなければプロトタイプ宣言の意味がない.

minoa_
質問者

お礼

すみません、質問する際の記述ミスです。。。 本当はmain.cでもfunc{1-3}.hをincludeしています。 失礼致しました。 いろいろ意見を頂いて参考になりましたが、 まだ他の方の異なる意見が伺えるかもしれないので、 もう少しの間、締め切らず残しておきます。 よろしくお願いします。

  • riwity
  • ベストアンサー率58% (7/12)
回答No.4

私は普通にやっているので、おかしくは無いと思います。 しかし、このままでは問題があります。 インクルードガードが無いので、「A_MAXが再定義されています」みたいなエラーが発生するはずです。 対策は下記のどちらかです。ともにdefine.hです。 方法1------------------------------ #pragma once // ~~内容~~ ----------------------------------- 方法2----------------------------- #ifndef DEFINE_H // 文字は任意。 #define DEFINE_H // 二つが同じで他と被らない。 // ~~内容~~ #endif -----------------------------------

minoa_
質問者

お礼

今回の場合エラーは出ていないようですが、 defineなどの再定義を防ぐコーディング手法として勉強になりました。 ご意見のほうも、ありがとうございました。

  • riwity
  • ベストアンサー率58% (7/12)
回答No.3

私は普通にやっているので、おかしくは無いと思います。 しかし、このままでは問題があります。 define.hはその中のマクロを使うクラスのヘッダ全てにincludeしますが、読み込みは一度だけにしましょう。 でなければ「A_MAXが再定義されています」みたいなエラーが発生します。 具体的には下のいづれかをします。ともにdefine.hです。 方法1------------------------------ #pragma once // ~~内容~~ ----------------------------------- 方法2----------------------------- #ifndef DEFINE_H // 文字は任意。 #define DEFINE_H // 二つが同じで他と被らない。 // ~~内容~~ #endif -----------------------------------

  • Yanch
  • ベストアンサー率50% (114/225)
回答No.1

> void func1(int hoge); //プロトタイプ宣言 > void func1() > { > hogehoge; > } プロトタイプ宣言と、実体で、func1のシグニチャが一致していないのは、まずいかと思われます。

minoa_
質問者

お礼

すみません、質問する際の記述ミスです。。。 失礼いたしました。

関連するQ&A

  • 分割コンパイルについて

    現在分割コンパイルが分からずに苦戦しています。 下記のリストは構造体を使わなければコンパイラを通すことができましたが、 使うとなぜか通りません。 あれこれ試しましたがどうしても分かりません。 何がおかしいのでしょうか? *define.hで全てのファイルへの定義や宣言を行わせています。 ////////////// //Main.cpp ////////////// #include <stdio.h> #include <conio.h> #include "define.h" int main( void ){ Tmp[0].c = 15; printf("a: %d\n", a); printf("b: %d\n", b); printf("c: %d\n", Tmp[0].c); printf("NUM:%d\n", NUM); aaa(); bbb(); getch(); return 0; } ////////////////// // A.cpp ///////////////// #include <stdio.h> #include "define.h" void aaa( void ){ printf("a: %d\n", a); printf("b: %d\n", b); printf("c: %d\n", Tmp[0].c); printf("NUM:%d\n", NUM); } ////////////////// // B.cpp ///////////////// #include <stdio.h> #include "define.h" void bbb( void ){ printf("a: %d\n", a); printf("b: %d\n", b); printf("c: %d\n", Tmp[0].c); printf("NUM:%d\n", NUM); } ////////////////// // define.cpp ///////////////// #include "define.h" int a = 10; int b = 20; struct Parameter { int c; }; struct Parameter Tmp[NUM]; ////////////////// // define.h ///////////////// #define NUM 100 extern int a; extern int b; extern struct Parameter Tmp[NUM]; void aaa( void ); void bbb( void );

  • ヘッダファイルの2重のインクルードについて

    ある書物に「ヘッダファイルを複数回インクルードすると、それを”再定義”することによるエラーになる」と書いてありますたが、以下のようなヘッダファイルを作りそれを数回インクルードしても何ら異状が無くコンパイルできました。 math.h→ヘッダファイル名 #define max(a,b)  ((a)>(b)?(a):(b))→ヘッダファイルの内容 c ファイル #include<stdio.h> #include"math.h"←複数回インクルード #include"math.h"←複数回インクルード int main(void){ int x=1,y=2; printf("max(x,y)=%d\n",max(x,y)); return 0; } 環境としては、RedHat Linuxでviです。 何ゆえ、エラーにならないのか良く解りません。 宜しくお願いします。

  • 分割コンパイルの初歩

    C言語ですが、.hに実装を書くのは避けたほうが良いといわれます。 私は main.c define.h aaa.h bbb.h みたいなスタイルでコードを書いていました。 まずdefine.hでグローバル変数や、マクロなどの宣言を まとめて行い、ほかの.hやmain.cでも使えるようにして いました。 しかし、以下のような状況のとき、どのように分割すれば 良いのかが分かりません・・・。 たとえば、以下のように、マクロNUM、変数a,bをすべてのファイルで共有して使えるように分割コンパイルするにはどのようにコードを書き直せば良いのでしょうか? //--------------main.c------------------ #include "define.h" #include "aaa.h" #include "bbb.h" int main( void ){   printf("%d", a);   printf("%d", b);   printf("%d", NUM);   aaa();   bbb();   return 0; } //------------define.h------------------ #define NUM 100 int a = 10; int b = 20; void aaa( void ); void bbb( void ); //------------aaa.h------------------ void aaa( void ){   printf("%d", a);   printf("%d", b);   printf("%d", NUM); } //------------bbb.h------------------ void bbb( void ){   printf("%d", a);   printf("%d", b);   printf("%d", NUM); }

  • C言語で再帰的処理が出来ない理由

    以下のサイトでC言語の勉強をしているのですが、このサイトのソースコードをコピペして実行してみたら上手くいきませんでした。 http://wisdom.sakura.ne.jp/programming/c/c30.html ========================== #include<stdio.h> void func(int ); int main() { func(0); printf("プログラムを終了します"); return 0; } void func(int max) { if (max <= 10000) { printf("%d\r",max); func(max + 1); } } ========================== 実行してみると、何故か4700~4800の辺りで止まってエラーになってしまいます。 どうしてエラーになるのでしょうか?

  • define で 配列

    #defineで配列を定義したいのですがこのようなことは可能でしょうか? ヘッダファイル(test.h)で #define MAX (2) int A[MAX]={20,30}; ソースファイルで #include <stdio.h> #include "test.h" int main(){ int i; for(i=0;i<MAX;i++){ printf("A[%d]=%d\n",i,A[i]); } return 0; } とやれば出来るのですが、このヘッダファイルを複数のソースで参照すると 多重定義であるとおこられてしまいます。 #defineで #define A[MAX] {20,30} のように配列を定義する方法は存在するのでしょうか? どなたか良い方法を御存じの方、ご教授お願いします。

  • C++のファイル分割でのエラーについて

    最近VC2008でC++の勉強を始めたのですが、ファイル分割でLNK2005エラーというのが発生し、解消できません。 インクルードガードは行ったのですが、どうしたらよいのか分かりません。 ソースコードはこんな感じです。 //main.cpp #include "sub.h" #include "res.h" bool main(){ calcx(m_x); calcy(m_y); } //res.h 共有変数の宣言 #ifndef __RES_H #define __RES_H int m_x; int m_y; #endif //sub.h 関数のプロトタイプ宣言を行う void calcx(); void calcy(); //sub.cpp 関数の定義を記述する #include "res.h" void calcx(int x){ m_x = x + 100; } void calcy(int y){ m_y = y + 200; } エラー: 1>Main.obj : error LNK2005: "int m_x" (?m_x@@3HA) は既に sub.obj で定義されています。 1>Main.obj : error LNK2005: "int m_y" (?m_y@@3HA) は既に sub.obj で定義されています。 上記のようなエラーを解消するにはどうしたら良いのでしょうか。 何がおかしいのか指摘をお願いします。

  • extern記憶クラス指定子を使う事について

    prg1.cpp----------------------------- #include<stdio.h> void func(void); int gg=5678; int main(void) { printf("main gg=%d\n",gg); func(); return 0; } ---------------------------------- prg2.cpp-------------------------- #include<stdio.h> extern int gg; void func(void) { printf("func gg=%d\n",gg); } ---------------------------------- 以上「prg1.cpp」と「prg2.cpp」という名前のふたつのファイルを作成し、「prg1.cpp」で宣言したグローバル変数を「prg2.cpp」で利用可能にしたいと思っています。 それには、「prg1.cppをコンパイルし、prg2.cppもコンパイルして、両者のオブジェクト(コンパイル後のファイル)をリンクする」と参考書には書いてあったのですが、どのようにしたらリンクされるのかわかりません。 prg.1cpp---------------------- #include<stdio.h> void func(void); int gg=5678; int main(void) { printf("main gg=%d\n",gg); func(); return 0; } #include<stdio.h> extern int gg; void func(void) { printf("func gg=%d\n",gg); } ------------------------------- 以上のように、「prg1.cpp」のファイルに1つにまとめれば、なぜかよくわかりませんが実行できました。 しかし「prg1.cpp」と、「prg2.cpp」をリンクさせてみたいので、教えていただけると嬉しいです。

  • C言語で直角三角形の斜辺を求めるプログラムについて

    「二辺の長さが与えられているとき、斜辺の長さを求めよ」という問題です。 #include <stdio.h> #include <math.h> #define a 3 #define b 4 int main (void) { double c=0; c=sqrt(a*a+b*b); printf("%f",c); return 0; } visual2010c++で作ったんですが、sqrtに下線がついて、コンパイルエラーしちゃいます。 すんごい初歩的なことなんだと思いますが、どこなのか気づけません。 どなたかよろしくお願いします。

  • ヘッダのインクルード時のエラー

    初歩的な質問で恐縮です。 以下のようなファイルの構成でc++のプログラムを組んでいます。 <header.h> class H { public: virtual void func() = 0; }; <fileA.cpp> #include "header.h" class A : public H { public: void func() {} }; <fileB.cpp> #include "header.h" class B : public H { public: void func() {} }; <main.cpp> #include "fileA.cpp" #include "fileB.cpp" int main() { A a; B b; a.func(); b.func(); return 0; } これをビルドしようとすると、「クラス"H"を再定義しようとしています」とエラーが出てコンパイルができません。理屈は分かるのですが、これの対処方法が分かりません。この場合、header.hはJAVAにおけるInterfaceのような役割としてそれを使うfileA.cpp、fileB.cppの両者にインクルードしておきたいのです。これはどのようにして対処すべきなのでしょうか?

  • 分割コンパイルの#defineについて

    分割コンパイルで ファイル1 #include <stdio.h> #define number 10 char string[number]; int main(void){ string[0]='a'; string[1]='b'; file_to(); return 0; } ファイル2 #include <stdio.h> #define number 10 extern char string[number]; void file_to(void){ /***何かの処理をする*****/ } って感じなんですけども、配列string の中身の値をdefineによって指定しているのですが、片方のdefineの値を変更する時、もう一つのdefineも手動で変更しています。関係するファイル数が多くなってくると大変なので、どれかのdefineの値を変化させたら自動的に他のdefineの値も変更するプログラムの組み方はありませんか? 質問がわかりにくいかも知れませんがよろしくお願いします。

専門家に質問してみよう