分割コンパイルについて

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
七誌

分割コンパイルについて

#1

投稿記事 by 七誌 » 16年前

分割コンパイルを勉強したく、ためしに作ってみているのですが、
どうにもうまくいかないところがあったので、質問させてもらいました。

分割コンパイルを使ってプログラムを作るときに、グローバル変数を使いのですが
それぞれのソースファイルで変数を共有することができません。
ヘッダファイルを用意し、そこで定義してそれぞれのソースファイルでインクルード
してみたのですが、「変数はすでに定義されています」というエラーがでてしまいました。
インクルードガードという方法を試してみたのですが、うまくいきません。
対処法を教えていただけないでしょうか。
実際に動かしてみたプログラムは下のものです。
具体的には、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

array

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

#2

投稿記事 by array » 16年前

多分、#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:分割コンパイルについて

#3

投稿記事 by 御津凪 » 16年前

> 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:分割コンパイルについて

#4

投稿記事 by 七誌 » 16年前

arrayさん御津凪さん、ありがとうございます。
externを使えばよかったんですね。無事動かすことができました。

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

Mist

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

#5

投稿記事 by Mist » 16年前

インクルードガードの宣言の仕方はあっています。
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:分割コンパイルについて

#6

投稿記事 by 七誌 » 16年前

一つのソースファイルが同じファイルをインクルードするのを防ぐ方法だったんですね。
よくわかりました。
Mistさん、ありがとうございました。

閉鎖

“C言語何でも質問掲示板” へ戻る