2009-06-21 16 views
3

システム固有の機能を使用する必要があります。 ftello()(POSIX規格ではstdio.hで定義されています)。 また、標準のC++機能を使用する必要があります。 std::sprintf()(ISO C++標準に従ってcstdioで定義されています)。<cstdio>と<stdio.h>の両方を含む正しい順序?

AFAIK(<cstdio>のみを含む)は、非標準C++の定義を保証するものではありませんので、両方を含める必要があります。 私は長い間、(例えば)gccでインクルードファイルの順序に問題があるかもしれないことを以前読んだことがあります。

<cstdio><stdio.h>の両方を含める正しい順序は何ですか? 私は可能な限りクロスプラットフォーム(少なくともgcc、suncc、intel C++/linux、mingw)の解決策を探しています。

答えて

2

OK、最後に、C++ヘッダーを最初に含めて、Cヘッダーを後で行うのが正しいことを結論に達しました。例えば 、(GCC)から以下のC++ 0Xヘッダ検討:

/usr/include/c++/4.3/tr1_impl/cstdint:


// ... 
#define __STDC_LIMIT_MACROS 
#define __STDC_CONSTANT_MACROS 
#include_next <stdint.h> 
// ... 

それは何が2つのC99を定義することですC99 stdint.hヘッダーのみが含まれています。その理由はC99では、stdint.hの機能のいくつかはオプションであり、それらのマクロが定義されている場合にのみ利用可能です。ただし、C++ 0xでは、すべてのstdint.h機能は必須です。 今、C99 stdint.hを最初にcstdintに含めると、stdint.hのヘッダーガードのために必須のC++ 0x機能が得られません。 これはコンパイラベンダーの欠陥であると主張するかもしれないが、それは間違っているだろう。 stdint.hはシステムバンドルヘッダ(この場合はglibcから)です。これはC99ヘッダであり、C++ 0x(これは古いシステムでも構いません)またはgccについては何も知らないものです。コンパイラは実際にすべてのシステムヘッダを修正することはできません(この場合は常にC++モードでこれらの機能を有効にする)。しかし、C++ 0xサポートをこれらのシステムに提供する必要があるため、代わりにこの回避策を使用する。

2

システムヘッダファイルの場合、インクルードの順序は一般的にエラーの原因ではありません。

その他のヘッダーファイルについては、similar question here at SOをご覧ください。

+0

お返事ありがとうございます。 は、私はここに同様の問題を見つけたと思う: http://gcc.gnu.org/ml/libstdc++/2003-01/msg00210.html 私は実際にしばらく前に、それに出くわし、私は覚えていません詳細。ヘッダーは間違いなくシステムを介していた。 これはシステム/コンパイラの問題ですが、私はこの種のものを扱う試みの方法を誰かが知っているかもしれないということを尋ねていました。 – Alex

0

私が知ることから、ftello()とsprintf()はどちらもstdio.hに含まれています。

標準以外のヘッダーの場合は、依存関係の構造を調べて、どちらが他の依存関係に依存しているかを調べ、正しい順序で組み込む必要があります。

このため、インクルードファイルの依存関係は、インクルードファイルに含めて、適切にインクルードされるように「ユーザー」に依存しないようにしてください。

+0

はい、ftello()とsprintf()はstdio.hからのものですが、私はstd :: sprintf()について言及していますが、sprintf()と同じでも異なっていてもかまいません。実際には、sprintf()は通常はコンパイラ定義のマクロであるため、std :: sprintf()は関数であることが保証されているため(おそらくアドレスを取ることができる)、おそらくそうではありません。 したがって、stdio.hのftello()とcstdioのstd :: sprintf()を使用する必要があります。 どちらも標準のインクルードファイルからのものですが、これらの2つのファイルには特殊な関係があるため、様々なコンパイラ/ OSの組み合わせで確実に動作する正しい順序がわかりません。 – Alex

2

私は実際のルールはわかりませんが、一般的に言えば、上位レベルのライブラリの前に下位レベルのシステムライブラリを含めています。

この場合、stdio.hはCヘッダーであり、私の想像力はマシンに近く、<cstdio>はより抽象度の高いC++標準ライブラリです。

私はstdio.hの前に自分自身でcstdioを含める傾向がありますが、その根拠をサポートする正確な理由はわかりません。

0

あなたは正当な理由を心配しています。 <cstdio>の内容は、「包まれているかのように」<stdio.h>(17.4.1.2ヘッダー/ 4)の内容です。しかし、宣言と定義(マクロではない)は名前空間stdにあります。

したがって、std::ftello()と書く必要があります。携帯性を向上させるために、using std::ftello;を投げてください。そのことについても気にする必要はありません。

+0

ftello()はC++標準ではなく、std名前空間にftello()はありません(少なくともgccのlibstdC++では)。とにかくありがとう! – Alex

+0

それはまさに私の要点です。 C++標準では、stdio.hにあるものを正確に指定していません。 cstdioにはstdio.hにあるものはすべて含まれていますが、名前空間stdには含まれているだけです。 libstdC++がftelloをstdio.hに入れますがcstdioに入れない場合は、17.4.1.2に違反します。 – MSalters

0

私は一番上に最も特殊なものを、一番下には最も特殊なものを置いています。任意の

  • このソースファイルのヘッダ
  • プロジェクトは、この内のインスタンスライブラリの
  • ほとんど固有のライブラリが含まれている場合、

    1. プリコンパイルヘッダ:例えば、ソースファイルの場合、それは次のようになります。プロジェクト、または会社ライブラリ
    2. なブーストのような "システム" ライブラリなどの
    3. 最小固有のライブラリ、またはSDL
    4. 標準C++
    5. 標準C
    6. オペレーティングシステムヘッダ

    私の正当化は、より具体的なヘッダは、多くの場合、より一般的なヘッダを含め、マクロ経由でそれらを変更したいということです。これらが既に含まれている場合は、ガードをインクルードするか、デフォルトのマクロ値がシステムライブラリの動作を邪魔します。

    もう1つの理由は、他のソースファイルからインクルードされていても、それ以前にシステムライブラリが含まれていたため、他のヘッダーからの依存関係を隠すことができないことです。

  • +0

    それも私の包摂命令です。 :)私は何らかの理由で5を8の後に移動することを除いて。 –

    関連する問題