ページ 11

構造体の使用方法

Posted: 2012年7月14日(土) 06:04
by こんばんは
ファイル分割をしていくうちに、構造体を2つのソースファイルで使用したいと思い、分けたのですがerrorLNK2005:"struct~~~は既に定義されています。と エラーになってしまいます。

構造体を2つのソースファイルで使用する方法を何方かご教授お願い致します。
-------------struct.h----------------
struct ABC
{
int x;
int y;
};

ABC abc[] = {
{10,20},{30,40}
};
---------------
---------spot.c-------------
void Spot(int xx, int yy, int num)
{
int x = abc[num].x;
int y = abc[num].y;
---------------
---------nip.c-------------
void Spot(int xx, int yy, int num)
{
int x = abc[num].x;
int y = abc[num].y;
---------------

Re: 構造体の使用方法

Posted: 2012年7月14日(土) 06:42
by へにっくす
えーとソースの掲示にはcodeタグを使ってください。
とひとまず注意したとこで本題。

ヘッダーには宣言のみ記述できます。

コード:

ABC abc[] = {
{10,20},{30,40}
};
のように実体をヘッダーに書くことはできません。
なぜなら#includeしたソースそれぞれに同じ名前の実体が作成され、
リンクするときに各ソースに存在する同じ名前でエラーになります。
なのでグローバル変数として宣言するなら、ヘッダーには

コード:

extern ABC abc[];
だけにして、そのヘッダーを#includeしているCソースに移動しましょう。
もちろん一つのCソースにだけですよ? 笑

分割の定石
http://homepage3.nifty.com/mmgames/c_guide/20-02.html

Re: 構造体の使用方法

Posted: 2012年7月14日(土) 06:47
by box
コンパイルが通ったとしても、今度はリンク時に、
Spot関数の定義が複数あるという理由で失敗しそうな気がします。
気のせいかもしれません。

【追記】
失礼しました。もともと、リンク時の話でしたね。

Re: 構造体の使用方法

Posted: 2012年7月14日(土) 06:59
by こんばんは
codeタグ申し訳ありません。

へにっくす様、返信ありがとうございます。

「分割の定石」こちらのサイトや「Ryujin5章~10章」などは実はファイル分割のさい大変お世話になったサイトです。

一つのCソースだけ・・・・。

ヘッダーに構造体を書いたのが間違いでしょか。

Re: 構造体の使用方法

Posted: 2012年7月14日(土) 07:04
by こんばんは
失礼しました、下記なおしました

コード:

-------------struct.h----------------
struct ABC
{
	int x;
	int y;
};

ABC abc[] = {
	{10,20},{30,40}
};
---------------
---------spot.c-------------
void Spot(int xx, int yy, int num)
{
	int x = abc[num].x;
	int y = abc[num].y;
---------------
---------nip.c-------------
void nip(int xx, int yy, int num)
{
	int x = abc[num].x;
	int y = abc[num].y;
---------------

Re: 構造体の使用方法

Posted: 2012年7月14日(土) 07:13
by box
こんばんは さんが書きました: errorLNK2005:"struct~~~は既に定義されています。と エラーになってしまいます。
~~~の部分が肝心なので、できれば省略せずに、全文を正確に載せてくださるとおおいに助かります。
こんばんは さんが書きました:

コード:

-------------struct.h----------------
struct ABC
{
	int x;
	int y;
};

ABC abc[] = {
	{10,20},{30,40}
};
---------------
配列abc[]の定義をヘッダーファイルの中に書くことの是非はともかくとして、
C言語の場合、配列定義時のABCの前にstructが必要ではないのかなぁ、という気がします。
コンパイルエラーは出なかったのでしょうか?
それから、
こんばんは さんが書きました:

コード:

---------spot.c-------------
void Spot(int xx, int yy, int num)
{
	int x = abc[num].x;
	int y = abc[num].y;
---------------
---------nip.c-------------
void Spot(int xx, int yy, int num)
{
	int x = abc[num].x;
	int y = abc[num].y;
---------------
この2個の.cファイルでは、間違いなくstruct.hをインクルードしているのですね?
コードを貼り付けるときは、そういうところも見せていただきたいんですよね。

Re: 構造体の使用方法

Posted: 2012年7月14日(土) 07:34
by こんばんは
BOX様 返信ありがとうございます

エラー文書き込みましたので確認お願いいたします

コード:

---------spot.c-------------
#include "struct.h"

void Spot(int xx, int yy, int num)
{
    int x = abc[num].x;
    int y = abc[num].y;
---------------
---------nip.c-------------
#include "struct.h"

void Spot(int xx, int yy, int num)
{
    int x = abc[num].x;
    int y = abc[num].y;
---------------
1>nip.obj : error LNK2005: "struct ABC * abc" (?abc@@3PAUABC@@A) は既に Spot.obj で定義されています。

.exe : fatal error LNK1169: 1 つ以上の複数回定義されているシンボルが見つかりました。

Re: 構造体の使用方法

Posted: 2012年7月14日(土) 07:49
by box
こんばんは さんが書きました: 1>nip.obj : error LNK2005: "struct ABC * abc" (?abc@@3PAUABC@@A) は既に Spot.obj で定義されています。

.exe : fatal error LNK1169: 1 つ以上の複数回定義されているシンボルが見つかりました。
本日6:42に投稿があった、へにっくすさんからの回答に従ってください。
回り道をさせてしまい、申し訳ありません。

Re: 構造体の使用方法

Posted: 2012年7月14日(土) 08:01
by へにっくす
こんばんは さんが書きました:
.exe : fatal error LNK1169: 1 つ以上の複数回定義されているシンボルが見つかりました。
これについては他の方が回答されているように、
2つのソースで同じ関数名があるからです。
どちらか一方を名前変えるか、staticというキーワードをいれるかしてください。
こんばんは さんが書きました:失礼しました、下記なおしました
codeタグをつけたのですね。
今度からはそうしてください。
box さんが書きました:C言語の場合、配列定義時のABCの前にstructが必要ではないのかなぁ、という気がします。
コンパイラはC++だったりすると通っちゃった記憶があります。。
#classと同様にみられるせいかね

Re: 構造体の使用方法

Posted: 2012年7月14日(土) 09:16
by naohiro19

コード:

struct ABC
{
	int x;
	int y;
};

ABC abc[] = {
	{10,20},
	{30,40}
};
これはCコードとしてコンパイルすると

コード:

1>main.c(11): error C2065: 'ABC' : 定義されていない識別子です。
1>main.c(11): error C2146: 構文エラー : ';' が、識別子 'abc' の前に必要です。
1>main.c(11): error C2065: 'abc' : 定義されていない識別子です。
1>main.c(11): error C2059: 構文エラー : ']'
といったエラーが出ますが structをつけなくてはいけません。もしくはtypedef キーワードを使って

コード:

typedef struct /*コンパイラは自動的に__unnamed_struct_0001_1を付けます。*/
{
	int x;
	int y;
}ABC;

ABC abc[] = {
	{10,20},
	{30,40}
};
のようにしないといけません。
[hr]
C++では 前者のコードはエラーも出ません。

Re: 構造体の使用方法

Posted: 2012年7月14日(土) 09:25
by こんばんは
へにっくす様 ありがとうございました。

どちらか一方の「名前変える」又は「staticというキーワードをいれる」
上記両方とも試、エラーは解消され起動できました。

staticについて調べました↓

変数や関数をファイル内のみで使用し、他に対しては公開したくない場合にこの方法をとります。
外部変数や関数に対してstaticを使用すると、静的な記憶クラス定義(値を保持 する事だと思います)となり、その外部変数や関数はそれが定義されたファイル(モジュール)以外からは

「参照することができなくなる。」 = 1 つ以上の複数回定義されているシンボルが見つからなくなる。

っと 解釈したんですが、どうでしょうか。

一応 解決! にしておきます、間違っておりましたら何方でもよろしいので返信頂けると有難いです。

Re: 構造体の使用方法

Posted: 2012年7月14日(土) 21:18
by へにっくす
こんばんは さんが書きました:「参照することができなくなる。」 = 1 つ以上の複数回定義されているシンボルが見つからなくなる。
その解釈であってます。
ただし同じ関数名ってことは、同じ処理してるってことではないのでしょうか?
同じ処理をしているなら、一方は削除するべきなんですけどね。
そしてヘッダーにはプロトタイプ宣言を載せる・・・とか。
それぞれのファイルで違う処理をしているなら、名前を変更するのが妥当です。
そのファイルの中でしか使用しない関数であれば、staticをつけるべきです。
両方することなかったんですよ?