ページ 11

分割コンパイルについて

Posted: 2008年10月08日(水) 00:19
by 七誌
分割コンパイルを勉強したく、ためしに作ってみているのですが、
どうにもうまくいかないところがあったので、質問させてもらいました。

分割コンパイルを使ってプログラムを作るときに、グローバル変数を使いのですが
それぞれのソースファイルで変数を共有することができません。
ヘッダファイルを用意し、そこで定義してそれぞれのソースファイルでインクルード
してみたのですが、「変数はすでに定義されています」というエラーがでてしまいました。
インクルードガードという方法を試してみたのですが、うまくいきません。
対処法を教えていただけないでしょうか。
実際に動かしてみたプログラムは下のものです。
具体的には、aという変数をmain.cppとsub.cppの両方で使う方法を知りたいということです。
よろしくおねがいします。
// main.cpp
#include "stdio.h"
#include "ren.h"
int main (){
	printf ("%d\n", a);
	sub();
	return 0;
}

// sub.cpp
#include "stdio.h"
#include "ren.h"
void sub () {
	printf ("sub %d\n",a);
}

// ren.h
#ifndef REN_H
#define REN_H
int a;
void sub();
#endif

Re:分割コンパイルについて

Posted: 2008年10月08日(水) 06:46
by array
多分、#ifndef REN_Hが機能されてないからではないでしょうか、main.cppにの0行目に#define REN_H
を入れたらどうでしょうか。

(別解)----------------------------------------------
龍神録を参考にするなら

// main.cpp
#define _GLOBAL_INSTANCE_
#include "ren.h"
int main (){
	printf ("%d\n", a);
	sub();
	return 0;
}

// sub.cpp
#include "ren.h"
void sub () {
	printf ("sub %d\n",a);
}

// ren.h
#include "stdio.h"
#ifdef _GLOBAL_INSTANCE_
#define GLOBAL
#else
#define GLOBAL extern 
#endif

GLOBAL int a;
GLOBAL void sub();
で大丈夫だと思います。

Re:分割コンパイルについて

Posted: 2008年10月08日(水) 10:26
by 御津凪
> array さん
extern の説明をしていないのですが大丈夫でしょうか。

extern は、外部に変数や関数を間接的に用意させる(あると仮定する)ものです。
実体は定義されていないので、どこかで一つだけ実体を定義する必要があります。

下記は私なりの別解です。
// main.cpp
#include "ren.h"
int main (){
	printf ("%d\n", a);
	sub();
	return 0;
}

// sub.cpp
#include "ren.h"
void sub () {
	printf ("sub %d\n",a);
}

// grobal.cpp ← グローバル変数定義用
#include "ren.h"
int a;

// ren.h
#include "stdio.h"

extern int a;
extern void sub();
グローバル変数定義用に grobal.cpp を用意して、
そこで a を定義しています。

Re:分割コンパイルについて

Posted: 2008年10月08日(水) 20:17
by 七誌
arrayさん御津凪さん、ありがとうございます。
externを使えばよかったんですね。無事動かすことができました。

ところで、自分が使ったインクルードガードの方法ですが、この使い方は間違っているのでしょうか?
arrayさんが言う、#defineが機能していない、というのが少し気になったのですが、
よろしければ詳しく教えていただけないでしょうか。

Re:分割コンパイルについて

Posted: 2008年10月08日(水) 20:36
by Mist
インクルードガードの宣言の仕方はあっています。
arrayさんのはグローバル変数が多重定義されないための方法ですが、
七誌さんの方法は以下のような場合に使います。
a.h
struct hoge {
   int hogehoge;
};

b.h
#include "a.h"

c.h
#include "a.h"

d.c
#include "b.h"
#include "c.h"
この場合、d.cのコンパイル時struct hogeが2回定義されるため多重定義としてエラーになります。
この時、a.hを七誌さんのやり方でインクルードガードすると、c.hの中でインクルードされている
a.hはスキップされるのでエラーにならなくなります。

Re:分割コンパイルについて

Posted: 2008年10月08日(水) 21:57
by 七誌
一つのソースファイルが同じファイルをインクルードするのを防ぐ方法だったんですね。
よくわかりました。
Mistさん、ありがとうございました。