• 締切済み

複数ファイルによる共通の外部変数定義について

初歩的な質問なのですが、今各関数をファイルごとに分けて記述しようとしています。 ここで詰まっているのでできればご教授お願いします ファイル構成は プログラムファイル main.cpp sub.cpp ヘッダーファイル  myheader.h(main.cppとsub.cpp両方でインクルード) ヘッダーファイルには両方のプログラムファイルで使う変数が定義してあります。 それでmain.cppとsub.cpp両方で同じ変数を使いたいのですがコンパイルエラーが発生してしまいます。 内容はsub.obj側で「i(共通のループカウンタ)はmain.objですでに定義されています」というものです。 とにかく私のやりたいことはヘッダーに外部変数を定義して両方のプログラムファイルで使いたいというものです。 もしかしたらファイルを分けるにも何か設定が必要なのでしょうか? 私はただ[プロジェクト]→[プロジェクトに追加]→[新規作成]でソースファイルを作っているだけなんですが・・・ 上記の状態を回避する方法はあるのでしょうか?

みんなの回答

  • toysmith
  • ベストアンサー率37% (570/1525)
回答No.3

main.cpp: #define MAIN #include "myheader.h" sub.cpp #include "myheader.h" myheader.h: #ifdef MAIN #define PUBLIC #else #define PUBLIC extern #endif PUBLIC int i; これでどうでしょう。 カウンタのグローバル定義はいかがなものか?という論議の前に、ヘッダファイルをいじるならプリプロセッサ構文を理解しましょう。 プリプロセッサ構文、記憶クラスの機能を知れば「なぜカウンタをグローバル定義しない方が良いか」がわかるはずです。 もちろん、カウンタをグローバル定義した方が良いこともあります。

  • gimmick
  • ベストアンサー率49% (134/270)
回答No.2

>ヘッダーファイルでは宣言だけしかしてはいけないのでしょうか? 通常、ヘッダファイルでは変数の定義は行いません。複数のファイルからインクルードされた場合に重複定義のエラーとなるからです。そのため、ヘッダファイル内では宣言のみを行います。しかし、これだけだと変数の定義がありません。そのため、どこかで定義を記述する必要があります。 >または解説ページなどがあれば紹介だけでもお願いします 適当なページが思いつかないのですが、1つだけ挙げておきます。

参考URL:
http://www.catnet.ne.jp/kouno/c_faq/c1.html#7
  • gimmick
  • ベストアンサー率49% (134/270)
回答No.1

myheader.h内で変数を定義したのでは、main.cppとsub.cppの両方で変数が定義されることになります。ヘッダファイル内では宣言のみにしてください。具体的には、myheader.h内では「extern int i;」のように宣言し、main.cppかsub.cppのどちらか一方で「int i;」と定義してください。これでエラーがでなくなるはずです。 #ただし、ループカウンタをグローバル変数にするのはどうかと思いますが...。

blackcat3
質問者

お礼

gimmickさん、ありがとうございます 無事コンパイルが通りました^^ しかし・・・ヘッダーファイルでは宣言だけしかしてはいけないのでしょうか? それとプログラムファイルの中でもう一度定義しなおすのはなぜなんでしょうか? たぶんこれもC言語では基礎的なものだとは思うのですがそちらも教えてもらえないでしょうか? または解説ページなどがあれば紹介だけでもお願いします 今から自分でも調べてみるつもりです >#ただし、ループカウンタをグローバル変数にするのはどうかと思いますが...。 あ、これは例えであって実際にはしてません(^-^;

関連するQ&A

  • 複数ファイルから同じ関数の呼び出しできますか?

    今、クライアント・サーバーのプログラムを作っているのですが、クライアントとサーバの間の通信を暗号化しようとしています。 開発環境はVisualStudio2010のMFCを使っています。 サーバとクライアントのプログラムとを同一のプロジェクトにして、サーバとクライアントの起動をオプションで切り分けています。 しかし暗号モジュールは一つのファイルなので、これをp1.cppとしましょう。 サーバのファイルをmain.cpp クライアントをsub.cpp として、main.cppの方で#include "p1.cpp"とやっても、クライアントのソースからは関数が参照できません。 例えば g++ main.cpp sub.cpp として、両方に同じ関数を書くと2重定義になります。 クライアントのsub.cpp にも同じようにインクルードしてやると、再定義されてるとリンクエラーが出ます。どうすれば同じ関数を同一プロジェクト内で共有(他のファイルから参照)させることができますでしょうか? 解決法をよろしくお願いします。

  • 多重定義が起きている?--lnk2005エラー:VC++

    今つまずいている問題は、VC++2008環境下で、以下のような構造になっているプログラムにおいて、多重定義?されているのでコンパイルが通らないというものです。 ソースコードを載せることは大きすぎてできないので、問題となる部分の記述のみ抽出して書きます。 -------define.h---------- ・・・・(module.h内の関数に使われる型の定義など) --------------------------- -------module.h---------- #include "define.h" void mod_1(void){・・・} void mod_2(void){・・・} --------------------------- このように、2つのヘッダーファイルがあり、define.hをインクルードしてmodule.hを使うという構造です。 (一般的ではないようですが、module.h内にmod_1やmod_2の実体を書き込んでいます。) その中で、以下のようなcppソースファイルがあります。 -------Main.cpp---------- #include "module.h"   (他のMain.cpp内の関数の都合上、Main.cppでもmodule.hをインクルードしています。関係あるかもしれないと思い書きました。) int main(){ M(); N(); } ------------------------ -------M.cpp---------- #include "module.h" void M(void){ mod_1(); mod_2(); } ---------------------- -------N.cpp---------- #include "module.h" void N(void){ mod_1(); mod_2(); } ---------------------- とすると、コンパイルの結果は次のようになります。 1>N.obj : error LNK2005: "void __cdecl mod_1(void)" (?mod_1@@YAXXZ) は既に M.obj で定義されています。 1>N.obj : error LNK2005: "void __cdecl mod_2(void)" (?mod_2@@YAXXZ) は既に M.obj で定義されています。 多重定義や多重インクルードは起こしていないと思っていますが、M.cppとN.cpp内の定義が衝突する理由がわかりません。どなたか理由が思いつく方、教えていただけたら幸いです。お願いいたします!! ◆◆◆   ◆◆◆   ◆◆◆   ◆◆◆   ◆◆◆ ちなみに、たとえばMやNとまったく同じ「A.cpp」を作り、このように書いたとします。 -------A.cpp---------- #include "module.h" void A(void){ mod_1(); mod_2(); } ---------------------- そしてmain関数の中に、MやNと同様に『A();』を付け加えたとします。 すると、実行結果はこのようになります。 1>M.obj : error LNK2005: "void __cdecl mod_1(void)" (?mod_1@@YAXXZ) は既に A.obj で定義されています。 1>M.obj : error LNK2005: "void __cdecl mod_2(void)" (?mod_2@@YAXXZ) は既に A.obj で定義されています。 1>N.obj : error LNK2005: "void __cdecl mod_1(void)" (?mod_1@@YAXXZ) は既に A.obj で定義されています。 1>N.obj : error LNK2005: "void __cdecl mod_2(void)" (?mod_2@@YAXXZ) は既に A.obj で定義されています。 VC++はファイル名のアルファベット順にコンパイルするようですが、どちらにせよmain関数内で呼び出されていること以外何の関わりも無いはずのA、M、Nの中での出来事が、衝突する理由が、調べども思い当たりません。 お願いいたします。

  • 分割コンパイルの方法がわかりません‥(Studio.NET)

    mainとsubという2つのcppファイルと各ヘッダファイルで分割コンパイルを試みましたがうまくいきません・・。 何が間違っているのでしょう・・。 エラーメッセージ error LNK2005: "char * a" (?a@@3PADA)は既にmain.objで定義されています。 fatal error LNK1169: 1つ以上の複数回定義されているシンボルが見つかりました。 と表示されます。ファイルソースは以下です。どなたか教えてください>< ----------(main.h)---------- char a[100]; ----------(main.cpp)---------- #include<stdio.h> #include "main.h" #include "sub.h" int main(){  sprintf(a,"hello.");  sub_write();  return 0; } -----------(sub.h)----------- void sub_write(); -----------(sub.cpp)------------- #include <stdio.h> #include "main.h" #include "sub.h" void sab(){  printf("%s\n",a); } return; }

  • 1 つ以上の複数回定義されているシンボルが見つかりました

    こんにちは。 VC++を使ってプログラムを作っているのですが、コンパイルは通るのですが、リンク時に以下のエラーメッセージが出ます。どなたか解決方法を教えてください。 (仮にプロジェクト名をPROJECTとします。) リンク中... PROJECT.obj : error LNK2005: "struct AA pAA" (?pAA@@3UAA@@A) はすでに PROJECT.obj で定義されています Debug/PROJECT.exe : fatal error LNK1169: 1 つ以上の複数回定義されているシンボルが見つかりました link.exe の実行エラー 開発ツール:VC++6.0 MFCを使用しています。 OS:Windows XP SP2 上記現象の発生した契機は、ヘッダファイル内で定義している構造体に構造体変数を加えたことによります。 【発生前】 ・ヘッダ内 struct AA { }; ・ソース内 AA pAA; 【発生後】 ・ヘッダ内 struct AA { }pAA; ・ソース (ソース内での構造体変数の宣言を削除) 以上で、どなたか心当たりのある方はご教授をお願いいたします。

  • 動的ライブラリ中のグローバル変数

    以下の3行を前提条件とします。 メインのプログラムmainと動的ライブラリsub1.soとsub2.soがあります。 sub1.cとsub2.cにはsub.hというヘッダをインクルードしています。 mainはsub1.soおよびsub2.soを実行時に動的にリンクします。 ここでsub1.c中で int TEST=10;と変数を定義しました。 さらにsub.h中にextern int TEST;と変数を宣言しました。 そしてsub2.h中で if(TEST){…}と記述しました。 この状態でコンパイルを実行しました。 ここでmainを実行すると動きません。 調べてみるとsub2.soがTESTがundefined symbolとなっていました。 動的ライブラリ間での変数の共有の仕方は上の書き方では不正確なのでしょうか?

  • 他の.CPPファイルに定義した関数を呼び出す方法について

    新規作成したプロジェクトに、 以前自分が作成した.cppファイルと.hファイルを そのまま使えないかと考えています。 (※仮にそのファイルの名前を "define.cpp" "define.h" とします) プロジェクトに新規ファイル main.cpp を作成して、 define.hをインクルードし、 以下のようなテストのプログラムを組みました。 ・../util/define.cpp---------------------- #include <iostream> #include "define.h" void test(){ std::cout<<"test."<<std::endl; } ・../util/define.h------------------------ #pragma once void test(); ・main.cpp---------------------------- #include "../util/define.h" int main(){  test();  return 0; } 上記のソースを VisualC++7.0 でビルドすると、 main.cppの3行目で以下のようなエラーが出ました。 > LNK2019: 未解決の外部シンボル "void __cdecl test(void)" が関数 _main で参照されました VisualC++で「既存項目の追加」という項目より、 実体の定義されたdefine.cppをプロジェクトに追加していないため 当然といえば当然なのですが・・・ C言語でいうところの<stdio.h>等みたいに、 わざわざプロジェクトにCPPファイルを追加しなくても 関数を呼び出せるようには出来ないのでしょうか? 全ての関数と処理をヘッダーファイルに記述すると解決ですが 物凄く見辛いのでそれは避けたいのです。 また、色々なPC間で使っているため(学校のPCなので)、 ツール自体のプロパティを弄らない方法があるのでしたら、 多少面倒でもそちらの方が好ましいです。 追加する方法があるかどうか、 あればその方法をご存じでしたら教えていただければ嬉しいです。 よろしくお願いします。

  • 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 で定義されています。 上記のようなエラーを解消するにはどうしたら良いのでしょうか。 何がおかしいのか指摘をお願いします。

  • 一つのソースユニットを複数のプロジェクトで共有したい

    BCB5を使っています。 複数のプログラムで共通な関数について、それらのプログラムで共有できるソースユニットを作ることが出来たら便利だと思っていますが、そんなことは可能でしょうか? 今三つのプログラム(A.exe、B.exe、C.exe)があるとします。 これらのプログラムの一部には、全く同じ処理があります。 それを関数Zf()とします。 で、Z.cppというユニットにこの関数を記述し、三つのプロジェクトで共有するのです。 この関数は仕様が完全に決まってはおらず、試行錯誤しながら決めて行くことになっています。 修正が多発するのですが、Z.cppを一つ修正すれば、再コンパイルだけで反映するので便利だ、という考えです。 私の知識では、一つのプロジェクトに新たなソースユニットを作る場合、そのユニットでは、呼ぶ側のヘッダーをincludeする必要があります。 今回の場合は、Z.cppは三つのプロジェクトに登録するわけですから、三つのヘッダーをincludeすることになってしまいます。 A.hとB.hを見ると同じ名前の変数や関数があり、これを同時にincludeするとマズイ事になりそうな気がします。 呼ぶ側のヘッダーをincludeせずに共有することは可能なのでしょうか? ちなみに関数Zf()では、グローバル変数は使っていませんし、他のユーザ関数を呼ぶこともありません。 シロートの質問ですがよろしくお願いします。

  • 分割コンパイルの方法がわかりません‥(Studio.NET) →2

    先ほどはありがとうございました。 私の考え方が違っていたようで、 main.cpp で使っているグローバル変数をsub.cpp内で使いたい。 sub.cpp に記述している関数をmain.cppから呼び出したいときは どうしたらいいでしょうか? ヘッダファイルの書き方がわからないのです>< XPでStudio.NETでプログラミングしています。 よろしくお願いします><

  • const char*のグローバル変数として使うのはどうしたら良いでし

    const char*のグローバル変数として使うのはどうしたら良いでしょうか? 以下のような動作を実装しようとしています。 mainからデータファイルの値を読み込みます。 その際、読み込むデータファイルのファイル名は別のコンフィグファイルに記載されているので、コンフィグから、データファイルのファイル名を読み込んで、データファイルをオープンする必要があります。 これをファイルを分割して実装しているのですがうまくいきません。 説明のため、データファイル名をmainから出力する実際と同じファイル構成のコードを作成しました。 以下のように5つのファイルに分けています。この際、データファイルのファイル名をconst char* filenameとしています。 ソースファイル #1: main.cpp //util.cppでfilenameに設定されたファイル名を表示する。 ソースファイル #2: set_filename.cpp //グローバル変数であるfilenameにコンフィグファイルに記載されているファイル名を設定する関数が定義されています。 ヘッダファイル #1: etc.h   //filenameの宣言が記載されていて、main.cpp, set_filenameでincludeされている。 ヘッダファイル #2: global.h //filenameの定義が記載されている。 ヘッダファイル #3 : set_filename.h //set_filename.cpp関数のプロトタイプ宣言 このような場合、set_filename.cpp内の関数で設定したfilenameがmain内で違う値に変わってしまいます。下のソースの例では、data.txtと出力されるのが期待値ですが、ゴミ値が表示されます。環境はVisual C++ 2008です。 どうして、set_filenameで設定したファイル名が変わってしまうのでしょうか? また、所望の動作はどのようにソースを変えれば実装できるのでしょうか? サンプルのソースは以下のとおりです。 -----main.cpp---------------- #include "etc.h" #include "global.h" #include "util.h" using namespace std; void main() { ifstream ifs("config.txt"); set_filename(ifs);  //config.txtには「data.txt」と記載しています。 cout<<filename<<endl; } -- ---------set_filename.cpp------- #include "etc.h" #include "util.h" void set_filename(ifstream &ifs) { string temp; ifs>>temp; filename=temp.c_str(); cout<<filename<<endl; ifs.close(); } ---- ---------etc.h----------------- #include <fstream> #include <cstdio> #include <string> #include <iostream> extern const char* filename;  //データファイル名です。 -- ----global.h-------- const char* filename; -- ----set_filename.h--- using namespace std; void set_filename(ifstream &ifs); --

専門家に質問してみよう