プロが教える店舗&オフィスのセキュリティ対策術

こんにちは。
C言語のプログラミングをしているのですが、
multiple definition of '関数名'と出てしまいます。

・コンパイルするファイル
program1.c(main文)
program2.c(関数)
program3.c(関数)
すべてのソースファイルが、
header.hをincludeしています。
header.hではすべての関数のプロトタイプ宣言がされています。
program2.cに書いてある関数、test()はすべてのソースファイルで使用しています。

・cygwin上で実行したコマンド
gcc -Wall program1.c program2.c program3.c -o test

・エラーの文章
(パス省略)/ccst1v2u.o:program2.c:(.text+0x0): mult
iple definition of `_test'
(パス省略)/ccyUr2Ku.o:program1.c:(.text+0x0): first defi
ned here

このような事態に陥った場合の解決方法はどのようにすればよいでしょうか?

先輩から引き継いだ、もともと一つのソースファイルに書かれていた多数の関数を、利便性のために分割したところこのようなエラーが発生しました。
先輩から引き継いだもののため、本当の関数名など細かいことをこちらに書き込めないのですが、
出来る範囲で補足いたします。
どうかよろしくお願いいたします。

A 回答 (6件)

実際にサンプルを作って確認してみましたか?


以下、インデントに全角スペースを使っています。
ソースを公開できないということなので、アドバイスできるのはここまでです。

=======
header.h
=======
#ifndef _HEADER_H_
#define _HEADER_H_
#include <stdio.h>
#include <stdlib.h>
void test1(void);
void test2(void);
void test3(void);
#endif
=====
main.c
=====
#include "header.h"
int main(void)
{
  test1();
  test2();
  test3();
  return 0;
}
=====
test1.c
=====
#include "header.h"
void test1(void)
{
  printf("test1() called.\n");
}
=====
test2.c
=====
#include "header.h"
void test2(void)
{
  test1();
  printf("test2() called.\n");
}
=====
test3.c
=====
#include "header.h"
void test3(void)
{
  test1();
  test2();
  printf("test3() called.\n");
}
    • good
    • 0
この回答へのお礼

お手数をおかけしてすみません。
自分で試せばすぐできることなのに頭が回りませんでした(汗)
ソースコードまでご丁寧に書いてくださりありがとうございました。

回答いただいたプログラムではエラーもなく正常に動作しました。
なので、今エラーが出ているプログラムは何か見落としているダメな箇所があるはずだとわかりました。
何度も見返したつもりですが、もう一度戻ってみてみることにします。

回答本当にありがとうございました。

お礼日時:2007/07/25 18:08

>・エラーの文章


>(パス省略)/ccst1v2u.o:program2.c:(.text+0x0): multiple
> definition of `_test'
>(パス省略)/ccyUr2Ku.o:program1.c:(.text+0x0): first
> defined here
testがprogram2.cで多重定義されました、
testは既にprogram1.cで定義されています。
そのままですね。。。

シンボル'XXX'が多重定義されていることを意味します。
#4さんが書かれている通り、C++ではオーバロードと呼ばれる
機能を使って、同じ関数名(メソッド名)でも引数が違えば
複数定義することが可能です。しかし、C言語では同じシンボルを
もつ関数や変数は認められません。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

追加で質問させていただきたいのですが、
以下のような場合でソースファイルを分割したい場合どうすればいいのでしょうか?

・test.c
main():test1,2,3使用
test1()
test2():test1使用
test3():test1,2使用
のとき、
test.cを
・main.c:mainのみ
・test1.c:test1定義
・test2.c:test2定義
・test3.c:test3定義
の4枚に分割したい。

私はこのような場合に、header.hというtest1,2,3がプロトタイプ宣言されているヘッダーを作り、
すべての.cにインクルードするというやり方をとって失敗してしまったのです。

私の理解不足で申し訳ありませんが、
もしお時間がありましたら、回答いただけるとうれしいです。

お礼日時:2007/07/24 22:47

#3です。

訂正。
>C++だと、同じ関数名でも、引数リストが同じであれば
C++だと、同じ関数名でも、引数リストが異なれば
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

どうやらC++にすると平気なようなのですが、
コンパイルしてみたところ、
C++では禁止(?)のnewという名前の変数を多用しているので、
エラーが出てしまいました。
ただ、問題としているエラーは出なかったので、
その変数名を直せば行けるのでは、、、と感じます。
C++を勉強したことが無いので不安ですが、
試してみたいと思います。

また、prpgram1と2で同じものを定義しているとのことですが、
1ではtest()については定義していません。
使用はしています。
2にtest()の中身が書いてあり、
プロトタイプ宣言をしているheader.hを両方のプログラムがインクルードしています。

もし勘違いがあればすみません。

お礼日時:2007/07/24 22:37

見たまんまだと思うんだけど…。


program1.cとprogram2.cで、
同じ関数testを定義しているんじゃないでしょうか。

C++だと、同じ関数名でも、引数リストが同じであれば
多重定義が可能ですが、Cではできない(であってます?)と思います。

例えば、program1,2,3のファイル名の拡張子を
.cppにしてコンパイルしたらどうなるでしょうか?
    • good
    • 0

program1.c、program2.c、program3.cそれぞれをリンクするときの組み合わせ(依存関係)が発生して、gcc が test() 関数を複数定義していると認識している気がします。

試しに1つづつ分割してコンパイル
gcc -Wall -c -o program1.o program1.c
gcc -Wall -c -o program2.o program2.c
gcc -Wall -c -o program3.o program3.c
gcc -Wall -o test program1.o program2.o program3.o
するとどうなりますでしょうか。
※ 本来は Makefile で書いたほうが良いのですが。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
やってみましたが、同じエラー内容が出ました。。。

一つ一つのコンパイルは成功しましたが、
最後の合体でエラーが出てしまいました。。。

お礼日時:2007/07/23 09:59

単純に header.h にインクルードガードがかかっていないとか?

    • good
    • 0
この回答へのお礼

回答ありがとうございます。

インクルードガードとは、
#ifndef _HEADER_H_
#define _HEADER_H_
・・・
#endif
のことですよね??
上記のものならやってあります。

お礼日時:2007/07/23 09:53

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています


このQ&Aを見た人がよく見るQ&A