合計 昨日 今日

分割コンパイル時の構造体宣言

[このトピックは解決済みです]

フォーラムルール
フォーラムルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
Name: taku_s
[URL]
ぴよぴよ(541 ポイント)
Date: 2017年11月09日(木) 07:24
No: 1
(OFFLINE)

 分割コンパイル時の構造体宣言

初歩的な質問ですいませんが
分割コンパイルの時、双方のファイルで同じ構造体をを使いたい場合は、どうすれば良いでしょうか?

別名で同じ要素の構造体を宣言して使うしかないのでしょうか?

Name: box
[URL]
ハッカー(264,359 ポイント)
Date: 2017年11月09日(木) 09:27
No: 2
(OFFLINE)

 Re: 分割コンパイル時の構造体宣言

多重インクルードガード付きのヘッダーファイルを作成するのがよさそうです。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

Name: taku_s
[URL]
ぴよぴよ(541 ポイント)
Date: 2017年11月09日(木) 21:22
No: 3
(OFFLINE)

 Re: 分割コンパイル時の構造体宣言

boxさま
多重インクルードガードは、誤ったインクルードで、グローバル変数などの二重定義を防ぐ機能だとおもいますが、

今回、a.cppとb.cppの両ファイルでグローバルな構造体変数を使えないかと思っています。
a.cppで定義
コード[C++]: 全て選択
1
2
3
4
5
6
7
8
struct setdata{
   int value;
   int pos;
};
 
setdata current[] = {{20, 0}
                             {30, 5}
                             {50, 9}};

b.cppでcurrent[]を使いたい場合、一般の変数の場合、externで宣言すればコンパイルは通ると思いますが構造体の場合は
extern setdata current[] だとタイプ名が不明とのエラー
struct setdata{ ・・・ を書くとstructの二重定義のエラーになると思います。

このような場合、どのようにすればよいでしょうか?

Name: YuO
[URL]
ハッカー(153,998 ポイント)
Date: 2017年11月09日(木) 21:44
No: 4
(OFFLINE)

 Re: 分割コンパイル時の構造体宣言

taku_s さんが書きました:分割コンパイルの時、双方のファイルで同じ構造体をを使いたい場合は、どうすれば良いでしょうか?

そのような場合,通常はヘッダファイルを使います。

例えば,こんな感じで。
setdata.h
コード[C++]: 全て選択
1
2
3
4
5
6
7
8
#ifndef SETDATA_H_
#define SETDATA_H_
// 構造体の定義なので,インクルードガードが必要。
struct setdata{
   int value;
   int pos;
};
#endif

a.cpp
コード[C++]: 全て選択
1
2
3
4
5
6
7
8
#include "setdata.h"
 
setdata current[] =
{
    {20, 0},
    {30, 5},
    {50, 9}
};

b.cpp
コード[C++]: 全て選択
1
2
3
#include "setdata.h"
 
extern setdata current[];

Name: taku_s
[URL]
ぴよぴよ(541 ポイント)
Date: 2017年11月11日(土) 06:53
No: 5
(OFFLINE)

 Re: 分割コンパイル時の構造体宣言

boxさま、Yuoさま
ありがとうございました。無事にコンパイルできました。
ただ、未だにうまく理解できません。(^^;

#ifndef SETDATA_H_
#define SETDATA_H_ で一度だけ展開すると言うことは、
a.cppに構造体の宣言が展開され、b.cppには何も展開されないように思ってしまいます。
実際にはどうなのか、展開後のソースは見れないので、ここが上手く理解できますん。

また。私の理解では
g++ -c b.cpp a.cpp とやった場合は、
b.cpp側に構造体宣言が展開され、a.cppには何も展開されずエラーになりそうな気がします。
試してみたら、実際にはエラーにならないんですね。

ここの部分が、理解できません。

Name: YuO
[URL]
ハッカー(153,998 ポイント)
Date: 2017年11月11日(土) 14:08
No: 6
(OFFLINE)

 Re: 分割コンパイル時の構造体宣言

#defineによって定義されたシンボルは,コンパイルするソースファイルひとつの単位でのみ有効です。
コンパイラの引数に複数のソースファイルを書いても,基本的にコンパイラは個々にコンパイルを行います。
このため,#defineの定義は同時にコンパイラに渡された他のソースファイルの影響を受けません。

インクルードガードは,1つのソースファイルから,同一のファイルが(直接・間接問わず)複数回インクルードされた場合にエラーにならないようにする物です。
極端な例だと
コード[C++]: 全て選択
1
2
#include "setdata.h"
#include "setdata.h"
ですが,こういうことはまず起こりません。
実際にあるのは
  • a.cppはb.hとc.hをインクルード
  • c.hはb.hをインクルード
というような場合でしょうか。
この場合,a.cppという1つのソースファイルからb.hが2回インクルードされることになります。
このような場合にエラーにならないように,インクルードガードを行います。

Name: taku_s
[URL]
ぴよぴよ(541 ポイント)
Date: 2017年11月12日(日) 07:04
No: 7
(OFFLINE)

 Re: 分割コンパイル時の構造体宣言

[解決!]

Yuoさま
丁寧に対応して頂いてありがとうございました。
もともと、私の
「struct setdata{ ・・・ を書くとstructの二重定義のエラーになると思います。」 これが間違いだったんですね。
この思い込みがあったのでなかなか理解できませんでした。

ありがとうございました。


Return to C言語何でも質問掲示板

オンラインデータ

このフォーラムを閲覧中のユーザー: なし & ゲスト[13人]