「夫を成功」へ導く妻の秘訣 座談会

こんにちは。
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

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

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

このQ&Aに関連する最新のQ&A

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に関連する人気のQ&A

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

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

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Qint型からchar型への変換

タイトル通り、int型からchar型への変換の仕方がわかりません!><
どうしたらいいのでしょうか?

Aベストアンサー

#include <stdio.h>


char buf[5];
int no;

no = 10;
sprintf(buf, "%d", no);

Qファイルやディレクトリの存在確認を行う方法

ファイルをオープンするのはfopenでOKですが、ファイルやディレクトリの存在確認を行う方法が知りたいです。

何か組み合わせて作るものなのでしょうか?
perlとか便利な演算子があるのですが、C/C++って器用ではないですね。
これは処理系?依存の内容ですか?

私の環境は VC6, VC2005 Windows2000です。

Aベストアンサー

int access(const char* path, int mode);
int stat(const char* path, struct stat* sb);

かな?
MSDN を引くと _access_s() を使えとか書いてあるけど。

QC言語のポインターに関する警告

line[100]で
「1」が格納されていたら「a」
「2」が格納されていたら「b」
「3」が格納されていたら「c」
とout[100]に代入する関数を作りたいのですが
コンパイルすると関数の部分で
warning: assignment makes integer from pointer without a cast
という警告がでます。
ポインターは使っていないのですが、ポインターに関する警告が出ているようで困っています。
どこが悪いのかまったくわからなくて作業が完全に止まってしまいました。
解決法をおしえてください。お願いします。

/*宣言*/
int=i; /*main関数内のfor文で使用*/
char line[100], out[100];
void change(int);

/*関数*/
void change(int i)
  {
   if(line[i]=='1'){
    out[10]="a\0"
   }if(line[i]=='2'){
    out[10]="b\0";
   }if(line[i]=='3'){
    out[10]="c\0"
}
}

line[100]で
「1」が格納されていたら「a」
「2」が格納されていたら「b」
「3」が格納されていたら「c」
とout[100]に代入する関数を作りたいのですが
コンパイルすると関数の部分で
warning: assignment makes integer from pointer without a cast
という警告がでます。
ポインターは使っていないのですが、ポインターに関する警告が出ているようで困っています。
どこが悪いのかまったくわからなくて作業が完全に止まってしまいました。
解決法をおしえてください。お願いします。

/*宣言*/
int...続きを読む

Aベストアンサー

>    out[10]="a\0"
>    out[10]="b\0";
>    out[10]="c\0"

"a\0"や"b\0"や"c\0"は「charへのポインタ」ですよ。

out[10]は「char」ですから「記憶域が小さい整数(つまり、charに)に、ポインタを代入すると、値が失われるぞ」と警告が出ます。

void change(int i)
  {
   if(line[i]=='1'){
    out[10]='a';
   }if(line[i]=='2'){
    out[10]='b';
   }if(line[i]=='3'){
    out[10]='c';
}
}
または
void change(int i)
  {
   if(line[i]=='1'){
    out[10]=0x61; /* aのASCIIコード */
   }if(line[i]=='2'){
    out[10]=0x62; /* bのASCIIコード */
   }if(line[i]=='3'){
    out[10]=0x63; /* cのASCIIコード */
}
}
と書きましょう。

>    out[10]="a\0"
>    out[10]="b\0";
>    out[10]="c\0"

"a\0"や"b\0"や"c\0"は「charへのポインタ」ですよ。

out[10]は「char」ですから「記憶域が小さい整数(つまり、charに)に、ポインタを代入すると、値が失われるぞ」と警告が出ます。

void change(int i)
  {
   if(line[i]=='1'){
    out[10]='a';
   }if(line[i]=='2'){
    out[10]='b';
   }if(line[i]=='3'){
    out[10]='c';
}
}
または
void change(int i)
  {
   if(l...続きを読む

Qgcc: incompatible pointer type

以下のCソースでコンパイルすると、warning: passing arg 1 of `func_b' from incompatible pointer type
となります。
void (*p_func)() は、引数を省略しているので int として扱われるということでしょうか?

#include <stdio.h>
#include <stdlib.h>
void func_a( unsigned char x ){
printf( "x=%d\n", x ) ;
}
void func_b( void (*p_func)() ){
p_func( 1 ) ;
}
int main(){
func_b( func_a ) ;
return 0 ;
}

Aベストアンサー

まずは訂正から。

「関数や関数へのポインタを宣言するときに仮引数リストを空にすると、仮引数はないものとして扱われます。」と書きましたが、今の C の規格では
「関数を定義するときに仮引数リストを空にすると、仮引数はないものとして扱われます。これに対し、関数の(定義ではない)宣言や関数へのポインタの宣言(定義を含む)の場合には、引数の個数や型について一切情報が与えられないことを意味します。」くらいに解釈されます。将来的には変更されるはずですが。

今の場合 void (*p_func)() となっているので「p_func は void を返す関数で、その引数の個数や型は不明」ということになります。

ではなぜ unsigned char や unsigned short のときには warning が出るのに int や char * や long では出るのかという点に移るのですが、これはおそらく過去との互換性だと思います。ANSI/ISO C 以前、つまりいわゆる K&R の時代にはプロトタイプ宣言が存在しませんでした。この時代、char 及び short の引数は int に、また float の引数は double に自動的に変更されていました。つまり、関数の仮引数として char、short、float は許されていませんでした。

今考えている例では p_func に引数の情報が与えられていないため、その引数として char、short 及び float は許されず、その結果これらの型を持つ仮引数があるような関数を渡そうとすると warning が出るのだと思います。

まずは訂正から。

「関数や関数へのポインタを宣言するときに仮引数リストを空にすると、仮引数はないものとして扱われます。」と書きましたが、今の C の規格では
「関数を定義するときに仮引数リストを空にすると、仮引数はないものとして扱われます。これに対し、関数の(定義ではない)宣言や関数へのポインタの宣言(定義を含む)の場合には、引数の個数や型について一切情報が与えられないことを意味します。」くらいに解釈されます。将来的には変更されるはずですが。

今の場合 void (*p_func)() となっ...続きを読む

Q関数の実体定義にヘッダファイルの2重定義防止方法が効かない?

いつもお世話になっています。
MFCでCプログラミングをしています。

ヘッダファイルの2重定義防止のために、
ヘッダファイル全体を下記のように
囲みました。
<aaa.h>
#ifndef AAA
#define AAA
#define PI 3.141592
void Func();
int wa(int a, int b){
return a+b;
}
#endif

ビルドしたところ、
関数宣言(Func)や#define部分(PI)については、
2重定義が防止されているようなのですが、
関数の実体部分(関数wa)については、
2重定義防止機能が働かず、
***.obj : error LNK2005:
"int __cdecl wa(int a, int b)"
は既に ***.obj で定義されています。
というリンクエラーが表示されます。

関数の種類や
ヘッダファイル内の宣言の順番を
いろいろ変えてみたのですが同じ結果でした。

ここで、このヘッダファイルの先頭に
#pragma onceを使用すると
このリンクエラーは回避されるのですが、
他コンパイラとの互換性の観点から、
#pragma once以外の方法で実現する必要があるので、
困っています。

URLを検索してみたのですが、
このような特殊な場合について記述されているものは
見つけられませんでした。
どなたか解決法又はヒントをご教示頂ければ
ありがたいです。
よろしくお願いします。

いつもお世話になっています。
MFCでCプログラミングをしています。

ヘッダファイルの2重定義防止のために、
ヘッダファイル全体を下記のように
囲みました。
<aaa.h>
#ifndef AAA
#define AAA
#define PI 3.141592
void Func();
int wa(int a, int b){
return a+b;
}
#endif

ビルドしたところ、
関数宣言(Func)や#define部分(PI)については、
2重定義が防止されているようなのですが、
関数の実体部分(関数wa)については、
2重定義防止機能が働かず、
***.obj : error LNK20...続きを読む

Aベストアンサー

二重インクルードは防止できています。ただし、あくまで1つのコンパイル単位の中での話です。エラー内容から察すると、2つ以上のソースファイルでaaa.hをインクルードしていますね?コンパイル時点ではエラーにはならずに複数のobjファイルが生成されますが、リンク時にエラーが発生します。これは、リンク実行時に関数waの定義が複数のモジュールで発見されるためです。

このようなエラーを防ぐため、通常、ヘッダファイルで関数の定義は行わず、その代わりに

extern int wa(int a, int b);

のように宣言だけを記述します。関数定義はどこかのソースファイルで1回だけ行います。

QLinuxのgccのインクルードパス?

Linuxのgccで、インクルードファイルやライブラリのパスを設定する方法が知りたいのですが、gccについて詳しい書籍やサイトがありましたら、教えてください。

gccとccの違いも知りたいです。

例)
#include "example.h"

このままだと、example.hが無いと表示されます。

Aベストアンサー

標準ライブラリのパスは、gccのインストール時に指定して、Cプリプロセッサの中に組み込まれます。

#include "example.h"
は、まずカレントディレクトリを探し、次に gccコマンドラインの -I オプションで指定したディレクトリを探し、最後に標準ライブラリが探されます。

#include <example.h>
は、カレントディレクトリを探さない点が異なります。

ccも基本的には同じですが、Unixの種類によって機能が異なる可能性があります。Linuxの場合はcc=gccです。

Q#defineの定数を文字列として読み込む

#define A "xxx"
#define B "yyy"
と定義しておいて

scanf("%s", str)
で読み込んだ文字列strが
"xxx"だった場合、"yyy"だった場合のように分岐したいのですが
このとき

if(str == "xxx")
のように中身を指定するのではなく

if(str == AA)
のように定数で分岐させることってできますか?

上記のままではできませんが、何か特別な関数とかでできるのでしょうか?

Aベストアンサー

こんにちは。

やりたいことの解釈ですが、(※勘違いの場合はすみません。)

1)マクロの名前(定義名)が文字列として格納された文字列 str があるとする。
 例)
   #define A "xxx"  //マクロ名=A
   char str[] = "A";   //"A"はマクロ名

2)上記の文字列 str を関数 func に渡す際に、マクロ名ではなくそのマクロで
  定義された文字列を渡したい。
 例)
   func( str );    //←この場合
    ↓
   func( "xxx" );  //←として展開される

ということで宜しいでしょうか?

だとした場合、少し回りくどいやり方かもしれませんが、以下のような文字列
変換用のマクロを定義してみては如何でしょうか?
※基本的には、他の回答者の方と同じように strcmp関数 を使用します。

■マクロ例
==============================
//文字列を定義したマクロ …※1
#define A "xxx"
#define B "yyy"

//引数を文字列として取得するマクロ
#define GETSTR(x) #x

//引数をマクロ名としてそのマクロで定義された文字列を取得するマクロ …※2
//注)<string.h>がインクルードされていることを前提とする
#define STR2MAC(str) \
!strcmp(str,GETSTR(A))? A : \
!strcmp(str,GETSTR(B))? B : str
==============================

上記マクロを使用して、関数 func にマクロ名が格納された文字列 str を
渡す場合は、
   func( STR2MAC( str ) );
のような記述になります。

前提として、※2のマクロ内でstrcmp関数を用いて文字列の照合を行って
いますので、<string.h>のインクルードが必要になります。

また、※1の文字列を定義するマクロの種類(パターン)を増やす場合、
※2のマクロの判定文もそれに合わせて増やす必要があります。

上記のマクロを使用したサンプルソースを下記に掲載致します。
注)エラー処理は行っていません。

■サンプルソース
==============================
#include <stdio.h>
#include <string.h>

//文字列を定義したマクロ
#define A "xxx"
#define B "yyy"

//引数を文字列として取得するマクロ
#define GETSTR(x) #x

//引数をマクロ名としてそのマクロで定義された文字列を取得するマクロ
//注)<string.h>がインクルードされていることを前提とする
#define STR2MAC(str) \
!strcmp(str,GETSTR(A))? A : \
!strcmp(str,GETSTR(B))? B : str

//プロトタイプ
void funcHoge( const char *str );

int main(void)
{
char sArg[128];

printf( "A or B ?>" );
scanf( "%s", sArg );

printf( "string1: %s\n", sArg );
funcHoge( STR2MAC(sArg) );

return 0;
}

void funcHoge( const char *str )
{
printf( "string2: %s\n", str );
}
==============================

■上記サンプルの実行結果
≫実行その1≪
A or B ?>A
string1: A
string2: xxx

≫実行その2≪
A or B ?>B
string1: B
string2: yyy

≫実行その3≪
A or B ?>hoge
string1: hoge
string2: hoge

以上です。

こんにちは。

やりたいことの解釈ですが、(※勘違いの場合はすみません。)

1)マクロの名前(定義名)が文字列として格納された文字列 str があるとする。
 例)
   #define A "xxx"  //マクロ名=A
   char str[] = "A";   //"A"はマクロ名

2)上記の文字列 str を関数 func に渡す際に、マクロ名ではなくそのマクロで
  定義された文字列を渡したい。
 例)
   func( str );    //←この場合
    ↓
   func( "xxx" );  //←として展開される

ということで宜しいでしょう...続きを読む

Qビルド時のエラー

行列の計算をする関数をいくつか作り、
それをまとめたファイルmatrix.cを作りました。
自作関数の、M_ADD, M_SUBなどが含まれています。

mainのファイルでmatrix.cをインクルードして、
ビルドしようとしたところ、コンパイルはうまくいくのですが、
リンク時にエラーが起こってしまいました。

具体的には、以下のような感じです。

Linking...
matrix.obj : error LNK2005: _M_ADD already defined in main.obj
matrix.obj : error LNK2005: _M_SUB already defined in main.obj
Debug/計算.exe : fatal error LNK1169: one or more multiply defined symbols found
Error executing link.exe.



already defined と怒られていますが、
ほかの場所でそんな名前の関数を作った覚えはありません。
関数名をいろいろ変えてみてもだめでした。
ウェブサイトを調べてみても、見当たりませんでした。
これはどういうことなのでしょうか?
どうすれば解消できるのでしょうか?
どなたかわかるかた、教えていただけませんか?
よろしくお願いします。
ちなみに、Visual C++ 6.0を使用しています。

行列の計算をする関数をいくつか作り、
それをまとめたファイルmatrix.cを作りました。
自作関数の、M_ADD, M_SUBなどが含まれています。

mainのファイルでmatrix.cをインクルードして、
ビルドしようとしたところ、コンパイルはうまくいくのですが、
リンク時にエラーが起こってしまいました。

具体的には、以下のような感じです。

Linking...
matrix.obj : error LNK2005: _M_ADD already defined in main.obj
matrix.obj : error LNK2005: _M_SUB already defined in main.obj
Debug/計算.exe ...続きを読む

Aベストアンサー

matrix.cではなく、
matrix.hがあるならそれを#include するか
include せず、mainの上の方で
プロトタイプ宣言してください

void _M_ADD( ... );
って感じで。
あるいは matrix.cの関数の先頭にinlineってつけても回避できるかも。

そのエラーは関数の実態がある
matrix.cを2回以上includeしようとしているから
おきるのだと思われます。

Q「#undef」と「#define」の使い方について

代記のとおりですが、

#undef HENSU
#define HENSU 16MAX

という定義をした場合は、#undefで一旦定義を無効にして、
#defineで再定義されるという認識でよろしいでしょうか?

ご存知の方教えてくださいお願いします。

Aベストアンサー

よろしいです。

#ifdef HENSU
#undef HENSU
#endif
#define HENSU ...

の方がより安全かも。

Qfgetsで拾われる改行文字を削除したい

お世話になります

 C言語初心者のものです。今課題でC言語を用いたプログラミングを
Fedora上でやっています。問題は、fgetsでテキストファイルから、取得
した文字列の中から改行文字を削除できないことです。文字変数のアド
レスはわかっているのですが、終端文字に置換しようとすると、セグメ
ントエラーになってしまいます。これは如何にして解決すべきでしょう
か。よろしくお願いします。

Aベストアンサー

ポインタとかアドレスとか、C言語の用語としてあるものを別の意味に使うとまぎらわしいです。

「ポインタ」「アドレス」と言われたら、 この例なら str, str+i が思い浮びます。
「文字変数のアドレス」だと
char c ;
に対しての
&c
が思い浮びます。

配列なら「添字」、意味的には「x文字目」ですね。

> for(i=0;;i++){
> if(*(str+i)=='/n') {
> *(str+i)='\0';
> break;
> }
> }
/nが\nの間違いなら、この方法で半分正解です。もう少し広い範囲(可能なら全体)で見ないことにはなんとも言えません。
fgetsが最大文字数に達したり、ファイルの最後になったりで、strに改行文字が含まれない場合には、このループは止まりません(Segmentension Falutになって止まる)

・そのような状態になってないか、予めチェックする
・ループを終了させる仕組みを用意しておく
: forの終了条件を記述する、for中で if(*(str+i)=='\0') { break;} 等としておく、等
といった対策が必要です。


あと細かいところを言えば
・strを配列で用意したなら *(s+i)じゃなくてs[i]でいいんじゃないかな
・あるいは char *pみたいにしておいて、 iのループでなく pでループを組む( for(p=str;*p!='\0';p++) )とか。

ポインタとかアドレスとか、C言語の用語としてあるものを別の意味に使うとまぎらわしいです。

「ポインタ」「アドレス」と言われたら、 この例なら str, str+i が思い浮びます。
「文字変数のアドレス」だと
char c ;
に対しての
&c
が思い浮びます。

配列なら「添字」、意味的には「x文字目」ですね。

> for(i=0;;i++){
> if(*(str+i)=='/n') {
> *(str+i)='\0';
> break;
> }
> }
/nが\nの間違いなら、この方法で半分正解です。もう少し広い範囲(可能なら全体)で見ないことにはなんとも言えません。
fgetsが...続きを読む


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

人気Q&Aランキング