型の二重宣言 【C言語の相談】
-
HK
型の二重宣言 【C言語の相談】
こんにちは。 以前に以下のようなことがあって悩んでいたので質問させていただきます。
Cの話です。
大学で、ある研究分野で世界的に有名なオープンソースを動かして見ようと思い、ダウンロードしたのちにコンパイルしました。
すると、以下のようなコンパイルエラーが出ました。(Ubuntu11.10のgcc、Cygwinのgccの2通りを試しましたが結果は同じでした。)
fileio.h:69:7 error:conflicting types for 'getline'
/なんたらかんたら/stdio.h:37:9: note: previous declaration of 'getline' was here
すなわち、型の2重宣言ですね。
stdio.hに既に宣言されている型を、別のfileio.hというヘッダファイルで宣言してしまっている と私は解釈しました。
確かに、 fileio.h というヘッダファイルの中身を見てみると、69行目に getline という型を宣言している部分がありました。
この2重宣言を回避するために、私はfileio.h と他の「'getline'型を使っているファイル」の全てにおいて、「getline」を「getline42」のように置換しました。
その後、再度コンパイルしてみると、無事通り、プログラムも問題なく動きました。
・・・と、いうわけで、「問題を解決してほしい!」という類の質問ではないのですが、疑問に思ったことを相談させてください。
①世界的に有名であるオープンソースであるにも拘わらず、C言語標準ライブラリのstdio.hに含まれる型を使ってしまっているというミスは何故起きたのでしょうか。
②このような型の2重宣言をしてしまっているソースコードを直したい場合、私が行なった上記のような方法は良い方法と言えるでしょうか? (一気に置換しましたが、cファイルが多くてとてもめんどくさかったw) 他に良い方法はありませんか?
ちなみに そのオープンソースとは、SOM_PAK というもので、ここで手に入ります。
http://www.cis.hut.fi/research/som-rese ... rams.shtml
Cの話です。
大学で、ある研究分野で世界的に有名なオープンソースを動かして見ようと思い、ダウンロードしたのちにコンパイルしました。
すると、以下のようなコンパイルエラーが出ました。(Ubuntu11.10のgcc、Cygwinのgccの2通りを試しましたが結果は同じでした。)
fileio.h:69:7 error:conflicting types for 'getline'
/なんたらかんたら/stdio.h:37:9: note: previous declaration of 'getline' was here
すなわち、型の2重宣言ですね。
stdio.hに既に宣言されている型を、別のfileio.hというヘッダファイルで宣言してしまっている と私は解釈しました。
確かに、 fileio.h というヘッダファイルの中身を見てみると、69行目に getline という型を宣言している部分がありました。
この2重宣言を回避するために、私はfileio.h と他の「'getline'型を使っているファイル」の全てにおいて、「getline」を「getline42」のように置換しました。
その後、再度コンパイルしてみると、無事通り、プログラムも問題なく動きました。
・・・と、いうわけで、「問題を解決してほしい!」という類の質問ではないのですが、疑問に思ったことを相談させてください。
①世界的に有名であるオープンソースであるにも拘わらず、C言語標準ライブラリのstdio.hに含まれる型を使ってしまっているというミスは何故起きたのでしょうか。
②このような型の2重宣言をしてしまっているソースコードを直したい場合、私が行なった上記のような方法は良い方法と言えるでしょうか? (一気に置換しましたが、cファイルが多くてとてもめんどくさかったw) 他に良い方法はありませんか?
ちなみに そのオープンソースとは、SOM_PAK というもので、ここで手に入ります。
http://www.cis.hut.fi/research/som-rese ... rams.shtml
Re: 型の二重宣言 【C言語の相談】
getline関数はもともとGNU拡張の関数でしたが、最近POSIXになったようです。
参考http://linuxjm.sourceforge.jp/html/LDP_ ... ine.3.html
http://www.cis.hut.fi/research/som_pak/
から入手できるSOM_PAKは古いものですので、POSIXにgetlineがないころのものです。
SOM_PAKのドキュメントにもかかれている通り、このソフトは元々Unix向けに
作られており、GNU環境(GCC+glib)でコンパイルされることを意図されていない
と思われます。
ためしに/usr/include/stdio.hを見てみましょう。getlineのプロトタイプ宣言は
#if __USE_XOPEN2K8
#endif
で囲まれています。
makefileのCFLAGSに というふうに -ansi を追加してmakeしましょう。
参考http://linuxjm.sourceforge.jp/html/LDP_ ... ine.3.html
http://www.cis.hut.fi/research/som_pak/
から入手できるSOM_PAKは古いものですので、POSIXにgetlineがないころのものです。
SOM_PAKのドキュメントにもかかれている通り、このソフトは元々Unix向けに
作られており、GNU環境(GCC+glib)でコンパイルされることを意図されていない
と思われます。
getlineは純粋なCの標準関数ではないからです。①世界的に有名であるオープンソースであるにも拘わらず、C言語標準ライブラリのstdio.hに含まれる型を使ってしまっているというミスは何故起きたのでしょうか。
ためしに/usr/include/stdio.hを見てみましょう。getlineのプロトタイプ宣言は
#if __USE_XOPEN2K8
#endif
で囲まれています。
コンパイル時にANSI-Cモードでコンパイルすれば解決します。②このような型の2重宣言をしてしまっているソースコードを直したい場合、私が行なった上記のような方法は良い方法と言えるでしょうか? (一気に置換しましたが、cファイルが多くてとてもめんどくさかったw) 他に良い方法はありませんか?
makefileのCFLAGSに というふうに -ansi を追加してmakeしましょう。
Re: 型の二重宣言 【C言語の相談】
早速のご回答、また、本家のドキュメントの方まで見ていただいてありがとうございます!
なんかユーザー登録できたので、名前が変わってますが、私は質問者と同一人物です。
①の方は、理解することができました。確かに、このソースは90年代のもので、かなり古いですね。
②のほうですが、
ANSI-Cモードでコンパイルするためにmakefileを書き換えましたが
以前と同様のエラーが出ました。
具体的には、 となっている箇所を と変更しました。
ANSI-Cモードというのがイマイチわかっていないのに加え、makefileの書き方すらあまり知らないので(笑)、何をやっているのかわかっていません。
これからmakefileの書き方と、ANSI-Cについて少し勉強してみます。
もしよろしければ、ANSI-Cについて簡単にご教示ください
なんかユーザー登録できたので、名前が変わってますが、私は質問者と同一人物です。
①の方は、理解することができました。確かに、このソースは90年代のもので、かなり古いですね。
②のほうですが、
ANSI-Cモードでコンパイルするためにmakefileを書き換えましたが
以前と同様のエラーが出ました。
具体的には、 となっている箇所を と変更しました。
ANSI-Cモードというのがイマイチわかっていないのに加え、makefileの書き方すらあまり知らないので(笑)、何をやっているのかわかっていません。
これからmakefileの書き方と、ANSI-Cについて少し勉強してみます。
もしよろしければ、ANSI-Cについて簡単にご教示ください
Re: 型の二重宣言 【C言語の相談】
あら、僕がUbuntu10.04 + gcc 4.6で試したときはうまく行きましたが。
makefileはmakefile.unixを改名したもので、中身は となっています(コメントアウトしてある部分は省略しています)。
ANSI-CというのはC言語の規格の名前ですね。
一口にC言語と言っても、様々な規格があるのです。まあ歴史も長いですからね。
そのへんの話はANSI-Cも含めてhttp://ja.wikipedia.org/wiki/C%E8%A8%80%E8%AA%9Eが役立つと思います。
Re: 型の二重宣言 【C言語の相談】
ご回答頂きありがとうございます。
C言語の規格の記事を読みました。
-ansiとは、C89規格でコンパイルするときに使うんですね。
ところで、色々なサイトを見ていたら、同じような問題に関して言及してあるページが見つかりました。
yahoo!知恵袋
http://chiebukuro.spn.yahoo.co.jp/detail/q1260494702
今、ubuntuが使える環境にいなくて、先程のmakeはcygwinでやりました。
上のページに書いているように、cygwinに関しては
「/usr/include/stdio.h から /usr/include/sys/stdio.h の取り込み命令があり、そこに getline() の ifdef で保護された宣言がある」
ので、実際にsys/stdio.hの中を見てみると、
確かに で囲まれている宣言が見つかりました。 この部分さえ外してしまえば getline() の2重宣言を回避することができると思うのですが、いかがでしょう?
とはいえ、stdio.h本体を書き換えるというのは 良い方法とは言えませんよね。
こういう場合、どうすれば上記の部分を外してコンパイルすることが可能ですか?
なんか本質を理解せずに枝葉末節な質問をしている気がしますがご教示願います。
ちなみに、知恵袋には、「getline()を違う名前に置換する」 という、私がとった方法も 対処例のひとつとして挙げられていました。
置換の回数があまり多くない場合は、この方法でも十分かなと思いました。
C言語の規格の記事を読みました。
-ansiとは、C89規格でコンパイルするときに使うんですね。
ところで、色々なサイトを見ていたら、同じような問題に関して言及してあるページが見つかりました。
yahoo!知恵袋
http://chiebukuro.spn.yahoo.co.jp/detail/q1260494702
今、ubuntuが使える環境にいなくて、先程のmakeはcygwinでやりました。
上のページに書いているように、cygwinに関しては
「/usr/include/stdio.h から /usr/include/sys/stdio.h の取り込み命令があり、そこに getline() の ifdef で保護された宣言がある」
ので、実際にsys/stdio.hの中を見てみると、
確かに で囲まれている宣言が見つかりました。 この部分さえ外してしまえば getline() の2重宣言を回避することができると思うのですが、いかがでしょう?
とはいえ、stdio.h本体を書き換えるというのは 良い方法とは言えませんよね。
こういう場合、どうすれば上記の部分を外してコンパイルすることが可能ですか?
なんか本質を理解せずに枝葉末節な質問をしている気がしますがご教示願います。
ちなみに、知恵袋には、「getline()を違う名前に置換する」 という、私がとった方法も 対処例のひとつとして挙げられていました。
置換の回数があまり多くない場合は、この方法でも十分かなと思いました。
Re: 型の二重宣言 【C言語の相談】
ははあ、もしかしたらcygwinのstdio.hは、-ansiオプションを付けようが付けまいが、getlineのプロトタイプ宣言が有効になってしまう仕様のようですね。komachi さんが書きました:今、ubuntuが使える環境にいなくて、先程のmakeはcygwinでやりました。
上のページに書いているように、cygwinに関しては
「/usr/include/stdio.h から /usr/include/sys/stdio.h の取り込み命令があり、そこに getline() の ifdef で保護された宣言がある」
ので、実際にsys/stdio.hの中を見てみると、
確かに で囲まれている宣言が見つかりました。 この部分さえ外してしまえば getline() の2重宣言を回避することができると思うのですが、いかがでしょう?
とはいえ、stdio.h本体を書き換えるというのは 良い方法とは言えませんよね。
こういう場合、どうすれば上記の部分を外してコンパイルすることが可能ですか?
なんか本質を理解せずに枝葉末節な質問をしている気がしますがご教示願います。
ちなみに、知恵袋には、「getline()を違う名前に置換する」 という、私がとった方法も 対処例のひとつとして挙げられていました。
置換の回数があまり多くない場合は、この方法でも十分かなと思いました。
その場合は仕方ないですから、getlineを違う名前にする、という対処方にならざるを得ませんね。
その場合、各ファイルを手動で置換するのは面倒ですよね。
大丈夫、すべてのファイルを自動で置換することなんか簡単ですから。
http://blog.livedoor.jp/leaf_hiro/archi ... 81124.html
こんな感じで、findとperlを組み合わせれば、特定のディレクトリ以下すべてのファイルに対して一気に置換できます。
(すみません。cygwinで実行できるかは未確認です。findコマンドとperlコマンドが有れば出来るとは思いますが。)
Re: 型の二重宣言 【C言語の相談】
おお! なんと。素晴らしいことを教えていただきました。ありがとうございます。beatle さんが書きました:その場合、各ファイルを手動で置換するのは面倒ですよね。
大丈夫、すべてのファイルを自動で置換することなんか簡単ですから。
http://blog.livedoor.jp/leaf_hiro/archi ... 81124.html
こんな感じで、findとperlを組み合わせれば、特定のディレクトリ以下すべてのファイルに対して一気に置換できます。
cygwinでも無事にできました。この方法で置換してコンパイルしたものも、もちろん正しく動作しました。ありがとうございます。beatle さんが書きました:(すみません。cygwinで実行できるかは未確認です。findコマンドとperlコマンドが有れば出来るとは思いますが。)
Re: 型の二重宣言 【C言語の相談】
こんな風にすれば、stdlib.hの中のgetlineを別名にすり替えられませんか?
上のようなstdlib.hを作成し、そのファイルがあるディレクトリを-Iオプションで指定しておけばよいかと思います。
最後に編集したユーザー たかぎ on 2011年11月11日(金) 21:09 [ 編集 1 回目 ]
Re: 型の二重宣言 【C言語の相談】
ご回答頂きありがとうございます。
修正点も含め、全て納得いきました。
皆様ご協力頂き、本当にありがとうございました。
なるほど。たかぎ さんが書きました:私が書いた方法(一部間違っていたので修正しましたが...)なら、非破壊で対応できます。
修正点も含め、全て納得いきました。
皆様ご協力頂き、本当にありがとうございました。