web-dev-qa-db-ja.com

C ++プログラムに<xxxx.h>または<cxxxx>を含める必要がありますか?

  • C++プログラムに何を含めればよいですか、stdio.hまたはcstdio?なぜ?
  • 同じ機能を提供する2つのヘッダーファイルがあるのはなぜですか?
  • これに関して規格は何と言っていますか?
  • 他のそのようなヘッダーを含めるにはどうすればよいですか?従うべき基本ルールはありますか?
51
Alok Save

次のプログラムを検討してください。

サンプル1:

#include<stdio.h>

int main()
{
    printf("Hello World");
    return 0;
}

サンプル2:

#include<cstdio>

int main()
{
    printf("Hello World");
    return 0;
}

どちらも期待どおりに動作します。 どの使用法がより適切ですか?答えは次のとおりです:どちらでもない!驚き?読む。

C++標準ライブラリは互換性のためにすべての標準Cヘッダーを提供しますが、言語としてのC++も同等のヘッダーをすべて提供します。慣例として、

  • C++標準ライブラリヘッダー(C互換性のためにインクルードするものを除く)には、ファイル拡張子がありません。
  • Cヘッダーに相当するすべてのC++は、cxxxxxで始まります。

C++標準では、Annex D(規定)互換機能でこれについて言及しています。

Standard Citation

§2は、重要な区別点に言及しています。上記の例に適用されるこのルールは、次のことを意味します。

  • cstdioを含めると、シンボル名がstd名前空間にインポートされ、可能性がありますグローバル名前空間。
  • stdio.hを含めると、グローバル名前空間にシンボル名がインポートされ、可能性があります stdネームスペース。

このルールをサンプルコードに適用して、長所と短所を測定してみましょう。

サンプル1:これにより、グローバルネームスペースにstdio.hからすべてのシンボルがもたらされます。利点は、シンボルがグローバル名前空間にインポートされるため、修飾なしでシンボルを使用できることです。欠点は、おそらく使用しない多くのシンボル名でグローバル名前空間を汚染することです。これにより、シンボル名の衝突が発生する可能性があります。 C++では、常にグローバルネームスペースを地雷原と見なし、できる限り回避します。

サンプル2:これは、実装がシンボルをグローバル名前空間に配置する保証がないため、これは非常に悪い習慣です。標準では、そうする。私たちは単に、特定のコンパイラ実装の動作に依存しています。すべてのコンパイラがそうすることを想定することはできません。したがって、厳密に言えば、プログラムは標準承認されておらず、この使用法はすべての実装間で移植可能ではありません。

それで、正しい使い方は何ですか?

正しい使い方は、cstdioを使用してシンボル名を完全に修飾するか、using宣言。これにより、使用するすべてのシンボルがstd名前空間に存在し、グローバル名前空間を汚染しないことが保証されます。正しい使い方の例:

サンプル3:

#include<cstdio>

using std::printf;

int main()
{
    printf("Hello World");
    return 0;
}

ディレクティブ using namespace std;、特にヘッダーでは、良いオプションではありません であり、常にusing宣言を使用する必要があります。

stdio.hcstdioここでは、サンプルの使用例を示しますが、実際には すべて ほとんどのcxxxxxxxx.hヘッダー、 <math.h>および<cmath>

60
Alok Save

この投稿は少し古いので、以下を共有したいと思います:


コードを見る:

Using X.h   // Compatible with C language standard
---------------
#include <X.h>

int main() {
    // Invoke X's corresponding function
    return 0;
}

Using X    // Not compatible with C language standard
--------------
#include <X>

int main() {
    // Invoke X's corresponding function
    return 0;
}

どちらもコンパイルして実行できます。


C++ではどちらが優れていますか?

C++ 11C++ 17 の仕様について:

C.5.1(C++ 17ドキュメントのセクション)
ヘッダーの変更[diff.mods.to.headers]

  1. C標準ライブラリとの互換性のために、C++標準ライブラリはD.5で列挙されたCヘッダーを提供しますが、その使用はC++では非推奨です。

  2. Cヘッダー<stdatomic.h><stdnoreturn.h>、および<threads.h>のC++ヘッダーはなく、Cヘッダー自体もC++の一部ではありません。

  3. C++ヘッダー<ccomplex>(D.4.1)と<ctgmath>(D.4.4)、およびそれらに対応するCヘッダー<complex.h><tgmath.h>には、C標準ライブラリのコンテンツが含まれず、代わりにC++標準の他のヘッダーが含まれているだけです。図書館。


D.5C標準ライブラリヘッダー[depr.c.headers] 1. C標準ライブラリとの互換性のために、C++標準ライブラリは表141に示すCヘッダーを提供します。

enter image description here

C++ 11C++ 17の両方の標準仕様書には、C規格との互換性のために<X.h>の使用が残っていると記載されていますが、それらの使用はと見なされます。非推奨


C++ 20標準案について

彼らは、C++ 20でのCライブラリヘッダーの使用について"undeprecating"を検討しています。 <X.h>は緑色で強調表示されます。現在のところ、C++ 11およびC++ 17の非推奨は"weak Recommendation"および "C標準ライブラリヘッダー(c。 headers) "は以下に表示されます:

"基本的なCライブラリヘッダーは重要な互換性機能であり、すぐにはどこにも行かない。"(from C++ 20 review document


D.5 C標準
ライブラリヘッダー[depr.c.headers]

弱い推奨:上記に加えて、対応する<stdatomic.h><stdnoreturn.h>、または<threads.h>、ヘッダーがないため、C++標準から対応するCヘッダーも削除します。上記と同じですが、次の調整を行います。20.5.5.2.1 C標準ライブラリヘッダー[c.headers]

C標準ライブラリとの互換性のために、C++標準ライブラリは、表141に示すCヘッダーを提供します。表141 — Cヘッダー

 <assert.h>  <inttypes.h>   <signal.h>      <stdio.h>   <wchar.h>
 <complex.h> <iso646.h>     <stdalign.h>    <stdlib.h>  <wctype.h>
 <ctype.h>   <limits.h>     <stdarg.h>      <string.h>  
 <errno.h>   <locale.h>     <stdbool.h>     <tgmath.h>
 <fenv.h>    <math.h>       <stddef.h>      <time.h>
 <float.h>   <setjmp.h>     <stdint.h>      <uchar.h>

ヘッダー<complex.h>は、ヘッダー<complex>を単に含むかのように動作します。ヘッダー<tgmath.h>は、ヘッダー<complex>および<cmath>を単に含むかのように動作します。


Bjarne Stroustrup相互運用性の最大化CおよびC++言語間を推奨非互換性の削減できるだけ。他のものは、物事を複雑にするので、そうではないと主張します。

したがって、<X.h>どこにでもではないようです。最終的には、両方を使用できます。個人的には、どのコードを使用してコードを作成するかを決定しますCコードとの下位互換性かどうか。

5
Santiago Varela