2011-01-03 30 views
1

一部のソースコードをLinuxシステムに移植しようとしていますが、期待通りにいくつかの問題が壊れています。今のところ私の間違いを引き起こしているのは、誰かが.hと.cppファイルを持っていてfclose()を使うということです。ヘッダーファイルにソースコードを含める必要がありますか?

コンパイラはヘッダファイルにfclose()が宣言されていないと訴えています。それらがどのようにこれは前に働いて手に入れた - 私はこれは悪いスタイルだと思いますが、また、今

void closeFile() { if (fp) fclose(fp); } 

は、ここでは、ヘッダーファイル内の関数宣言をしましたか?コンパイラのバージョンでこのような動作が可能でしたか?

私は、ヘッダにはstdioを含めることによって、この問題を解決する、またはCPPに全体を動かすべきか?

+1

ヘッダーにコードを入れても文法的に間違ったことはありません。したがって、コンパイラはこれを "許可"することができます。これらのソリューションのいずれかが問題ありません。 – Falmarri

+3

C++コードでfcloseを使うのは、常に悪いスタイルです。 – BatchyX

+10

@BatchyX:すべての絶対的な非難は常に間違っています。 –

答えて

2

は、そのヘッダファイルは、(通常は)自分でコンパイルされていない点に注意してください。それらはソースファイルへの#include dであり、ヘッダーファイルが解析されたときに利用可能な定義は、問題のヘッダーファイルの上のソースファイルに含まれていたものです。

ヘッダーファイルがcloseFile()の実装に適した場所であるかどうかにかかわらず、ヘッダーファイルは、それ自身の先頭に必要なものすべてが#includeである必要があります。したがって、ヘッダーファイルの先頭に#include <stdio.h>を追加します。

(これは、Linuxカーネル自体にコンパイルすることを意図するものでコードされている場合は、stdio.h異なるヘッダを必要とするかもしれないことに注意してください。多くの場合、アプリケーション・レベル・ヘッダはカーネルソースで使用するのに適していない。)

+0

はい。これは、関数がヘッダーに関数の定義がある場合、関数が複数のオブジェクトファイルで定義されている可能性があり、リンカーがこれをリンクしたり同様にしないために問題を引き起こす可能性があります。 – BatchyX

+1

正しい。ヘッダファイルに定義されている関数は 'static'または' inline'でなければなりません。 –

6

悪いスタイルではありません、あなたはヘッダーファイルにソースコードを置くことができ、そしていくつかの時間が、あなたは特に、に強制している:テンプレートクラス/関数を定義するとき

  • インライン関数を定義します。

それはいつでも、ソースファイルには、このようなヘッダが含まれてコンパイルされるだろう(これはあなたを与えるので、とにかくあなたは、ヘッダファイルに(クラスのスコープ外で定義された)自由非インライン関数を置くべきではありませんリンクエラー)。

fcloseが宣言されていないというエラーが発生した場合は、そのコードの前にcstdio(またはstdio.h)が宣言されていない可能性があります。 #include <cstdio>をヘッダーファイルの先頭に置きます。

2

fclose()stdio.hがこのヘッダーに含まれていない場合、またはこのヘッダーが使用されるすべての場所の前に含まれていない場合は、未定義です。そのため、エラーが発生します。

それがある場合、私は個人的に、しかし、コードはヘッダファイルであることが許可されると間違って何も見えない、とあなたはC99を使用している、あなたは

inline void closeFile() { if (fp) fclose(fp); } 

それを宣言する必要がありますこれは、複数のコンパイルされたオブジェクトを意味し、 closeFile()シンボル(inlineのため)とコンパイラへのinlineヒントはありませんが、これは関数呼び出しとして残すべきではなく、代わりにinlineで置き換えてください。

+1

静的なインラインインラインが既に内部リンケージを持っている理由はありません。 –

+0

複数のコンパイル単位にヘッダが含まれている場合は、必ず 'static'が必要です。それはインラインであるべきですが、そうでないかもしれません。 'inline'キーワードを使うと、余分な機能を追加するべきではないとコンパイラに示唆されます。しかし、@ Giuliano0が指摘するように、 'inline'はインライン展開を保証しません。 –

+1

インラインでコードのインライン展開を保証することはできませんが、内部リンケージを保証します。したがって、 'static'は絶対に何も追加しません。 –

0

ヘッダーはテキスト置換によって含まれます(ヘッダーの内容全体が#include宣言に置換されています)。したがって、この特定のヘッダーを含む.cppファイルが1つしかない場合、これは.cppファイルで関数が定義されていることと同等です。私はこれが(リンク時に)働いていた理由だと思う。

C標準では、使用可能な機能を含めるために含める必要があるヘッダーしか定義しませんが、システムヘッダーが互いに組み込むことを禁じません。そのため、一部のシステムでは、stdio.hヘッダーが別のヘッダーに暗黙的に含まれている可能性があります(したがって、コンパイラによってエラーが報告されることはありません)。

個人的には、私は脆弱ではないので、このコードを.cppファイルに移動します(複数の.cppファイルでヘッダーを含めることができます。ヘッダーには先にstdio.hヘッダーを含める必要はありません)。実装を変更する必要がある場合(ファイルを閉じると失敗する可能性があるため、ロギングや適切なエラー処理を追加する必要がある場合)、再コンパイルを迅速に行うことができます。

3

他の回答について2つの点を追加するだけで、インラインは順序ではないことを覚えておいてください。強制的にをインラインにしない限り、コンパイラは何をすべきか推測します。ほとんどのコンパイラは、インラインで宣言していなくても、関数をいつインライン化するかを決めることができます。 でなければなりません。それはです。です。

実際には、関数/構造体/クラス定義をヘッダーに含める必要があります。時には、それらは些細でも単純でもない場合があります。しかし、これらの定義は、通常は必要な補助的な機能であり、単にファイルを整理するためにメインファイルに含めたくないのです。

このプラクティスについて私が今までに見た最良の例は、ゲームソースコードです(これは私の主な関心事です:))。

ところで場合ない限り、私は通常、(構造体や列挙型を除く)ヘッダファイル上の任意の宣言を入れないで、私は、分離されたファイル上に置く:

  • わずか数宣言/ AUX機能があります。作られる;または
  • これらの宣言は、別のコンテキスト(この場合は同じプロジェクト)で使用する関数であり、同じコンテキスト内で分離された「補助ライブラリ」として扱うほうがよいと思います。

ほんの少し助けてください。

+0

+1。 –

+0

異なるコンパイラでインライン展開を行う方法が異なります。だから彼らのドキュメントを読むことは良いです:) – Giuliano

関連する問題