#ifndefと#defineがC ++ヘッダーファイルで使用されるのはなぜですか?


496

通常、ヘッダーファイルの先頭に次のようなコードが表示されています。

#ifndef HEADERFILE_H
#define HEADERFILE_H

そして、ファイルの最後には

#endif

これの目的は何ですか?


36
+1-私も同じ疑問を抱いており、ここではるかに良い答えを得ました。将来の訪問者に役立つかもしれません:stackoverflow.com/q/3246803/1134940
Abid Rahman K

6
これに加えて、#pragma onceも使用できることを追加します。これは、あなたがしなければならないすべてであり、ifndefと同じ目的を果たします。2つの比較については、次を参照してください
ディメンション

3
a #pragmaが何であるかを言及するのが最善です。それはコンパイラ固有の機能をアクティブにします。#pragma onceされて非常に広くサポートされている、それは非標準です。
Potatoswatter 2013年

3
@Dimension:GNU独自のドキュメント(info cppまたはここを参照)は、「すべてのプリプロセッサで認識されているわけではないため、移植可能なプログラムでこれに依存することはできない」と述べています。そして、GNU cppは、一般的で移植可能な#ifndefイディオムを最適化するため、と同じくらい効率的#pragma onceです。
キーストンプソン

3
考慮すべき事項:アンダースコアで始まるマクロ名は使用しないでください。そのような識別子は実装に予約されています。より微妙に、#ifndef HEADERFILE_Hヘッダー名の実装の名前空間に違反する可能性がありEます。で始まる識別子Eと数字または大文字は、に予約されてい<errno.h>ます。提案し#ifndef H_HEADERFILEます。
キーストンプソン

回答:


527

それらは#includeガードと呼ばれます。

ヘッダーが含まれると、一意の値(この場合はHEADERFILE_H)が定義されているかどうかが確認されます。次に、定義されていない場合は定義し、ページの残りの部分に進みます。

コードが再度インクルードされると、最初のコードはifndef失敗し、空のファイルになります。

これにより、型、列挙型、静的変数などの識別子の二重宣言を防ぐことができます。


1
Koning Baard XIV:VCにも#pragma once同じことを行う:-)
Joey、

95
また、再帰的なインクルードを防止します... "alice.h"には "bob.h"が含まれ、 "bob.h"には "alice.h"が含まれますが、それらにはガードが含まれていません...
Kevin Dungs

@ケビン:それが私の言いたいことです。操作するフォームによって開かれたフォームを操作したかったのですが。それは私に多くのエラーを与え、私は何をすべきか分かりませんでした。私はあきらめました=)

6
@Јοеу:#pragma once移植性はありません。一般的な#ifndefイディオムが推奨されます。
キーストンプソン

2
@CIsForCookiesは、「1つの定義ルール」をお気に入りの検索エンジンにパンチします。
デビッドシュワルツ

33
#ifndef <token>
/* code */
#else
/* code to include if the token is defined */
#endif

#ifndef指定されたトークンが#definedファイル内またはインクルードファイル内で以前にあったかどうかを確認します。そうでない場合は、コードと終了の間にコードが含まれます。存在し#elseない場合#elseは、#endifステートメントが含まれます。#ifndefファイルがインクルードされた後にトークンを定義し、そのファイルの先頭にトークンが設定されていないことを確認することにより、ヘッダーファイルをべき等にするためによく使用されます。

#ifndef _INCL_GUARD
#define _INCL_GUARD
#endif

4
アンダースコアで始まる識別子は予約されています。自分で定義するべきではありません。のようなものを使用してください#ifndef H_HEADER_NAME
キーストンプソン

5
私はこれが古いコメントであることを知っていますが、実際にはアンダースコアの制限は、「外部識別子」、つまりコンパイル済みオブジェクトのシンボルテーブルに含まれる可能性のある識別子、つまりグローバル変数と関数名にのみ適用されます。マクロ名には適用されません。
2014年

1
Stuのコメントは本当ですか?私は単にstackoverflow.com/questions/228783/…を読んだだけで、今はよくわかりません。
ウィル

10

これにより、同じヘッダーファイルが複数回インクルードされるのを防ぐことができます。

#ifndef __COMMON_H__
#define __COMMON_H__
//header file content
#endif

このヘッダーファイルを複数のファイルに含めたとします。したがって、最初に__COMMON_H__が定義されていない場合、定義されてヘッダーファイルが含まれます。

次回__COMMON_H__が定義されているため、再度含まれません。


1

それらはifdefと呼ばれるか、ガードを含みます。

小さなプログラムを書く場合、それは必要ないように見えるかもしれませんが、プロジェクトが大きくなるにつれて、意図的または意図せずに1つのファイルを何度もインクルードする可能性があります。

#ifndef checks whether HEADERFILE_H is not declared.
#define will declare HEADERFILE_H once #ifndef generates true.
#endif is to know the scope of #ifndef i.e end of #ifndef

#ifndefがtrueを生成することを意味する宣言されていない場合、#ifndefと#endifの間の部分のみが実行され、それ以外の場合は実行されません。これにより、識別子、列挙型、構造体などが再び宣言されるのを防ぎます...

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.