web-dev-qa-db-ja.com

C / C ++コード用のプリプロセッサディレクティブ#ifndef

Eclipseでは、新しいC++クラス、または[〜#〜] c [〜#〜]ヘッダーファイルを作成するたびに、次のタイプの構造体を取得します。ヘッダーファイルexample.hを作成すると、次のようになります。

/*Comments*/
#ifndef EXAMPLE_H_
#define EXAMPLE_H_
/* Place to put all of my definitions etc. */
#endif

Ifndefは、EXAMPLE_H_が定義されていない場合は定義すると言っていると思います。これは、プロジェクトのコンパイルとリンクに使用しているツールによっては役立つ場合があります。ただし、2つの質問があります。

  1. これはかなり一般的ですか?あまり見かけません。そして、そのルーブリックを使用するのは良い考えですか、それともコードの定義にすぐに取り掛かる必要があります。

  2. 正確にはEXAMPLE_H_とは何ですか?なぜexample.h、または単なる例ではないのですか?それについて何か特別なことはありますか、それともEclipseがプロジェクトの自動ビルドを好む方法のアーティファクトである可能性がありますか?

17
Leif Andersen

これは一般的な構成です。物理ヘッダーファイルが複数回インクルードされている場合でも、ヘッダーファイルの内容をトランスレーションユニットに1回だけインクルードすることを目的としています。これは、たとえば、ヘッダーをソースファイルに直接含め、別のヘッダーを介して間接的に含める場合に発生する可能性があります。

コンテンツの周りに#ifndefラッパーを配置することは、コンパイラーがヘッダーのコンテンツを1回だけ解析し、再定義エラーを回避することを意味します。

一部のコンパイラでは、「#pragma once」で同じことを実行できますが、#ifndefコンストラクトはどこでも機能します。

15
user308405

これは、インクルードを保護するための一般的な方法です。このようにして、コードが2回インクルードされるのを防ぎます。また、使用される識別子は何でもかまいません。説明されている方法でそれを行うのは慣例です。

4
Jeff

それは一般的ですか?はい-all CおよびC++ヘッダーファイルは次のように構成する必要があります。 Example_Hはヘッダーガードであり、ヘッダー内のコードが同じ変換単位に複数回含まれることを防ぎます。これにより、複数の定義エラーが発生します。 EXAPMLE_Hという名前は、保護しているヘッダーファイルの名前と一致するように選択されます。プロジェクト内で一意である必要があり、場合によってはグローバルでも一意である必要があります。これを確実にするために、プロジェクト名の接頭辞または接尾辞を付けるのが通常です。

#define MYPROJ_EXAMPLE_H

たとえば、プロジェクトの名前が「myproj」の場合です。ちなみに、アンダースコアを前に付けると魔法のように一意になると考えたくはありません。_EXAMPLE_H___EXAMPLE_H__のような名前は、言語の実装用に予約されているため違法です。

4
anon

これは常にヘッダーファイルの先頭で行います。これは通常、ヘッダーガードまたはインクルードガードと呼ばれます。

ヘッダーファイルが複数回インクルードされる場合、1回だけインクルードされるようにします。そうしないと、複数回定義されていることなどについてエラーが発生することになります。

正確な定義はそれほど重要ではありませんが、通常はファイル名のバリエーションです。基本的に、指定されたマクロが定義されているかどうかを確認しています。まだ定義されていない場合は、それを定義して、ファイルのインクルードを続行します。含まれている場合は、以前にファイルをインクルードしている必要があり、ファイルの残りの部分は無視されます。

2

これはインクルードガードです。ヘッダーが1回だけ含まれることを保証します。

たとえば、次の場合:

#include "example.h"
#include "example.h"

ヘッダーが初めて含まれるとき、EXAMPLE_H_は定義されず、if-blockが入力されます。次に、EXAMPLE_H_#defineディレクティブによって定義され、ヘッダーの内容が評価されます。

2回目にヘッダーが含まれるときは、EXAMPLE_H_がすでに定義されているため、ifブロックは再入力されません。

これは、単一定義規則に違反しないようにするために不可欠です。インクルードガードがなく、そのヘッダーを2回インクルードしたヘッダーでクラスを定義すると、1つの定義ルールに違反するためにコンパイルエラーが発生します(クラスは2回定義されます)。

上記の例は簡単で、example.hを2回含めていることが簡単にわかりますが、ヘッダーには他のヘッダーが含まれていることが多く、それほど明白ではありません。

2
James McNellis

このことを考慮

ファイルfoo.c:

#include foo.h
#include bar.h

ファイルbar.h

#include <iostream>
#include foo.h

さて、foo.cをコンパイルすると、そこにfoo.hが2回あります。すべての関数が2回目にコンパイルエラーをスローするため、これは絶対に必要ありません。

これを防ぐために、INCLUDE GUARD 頂点で。そうすれば、すでに含まれている場合は、プリプロセッサ変数を定義して、再度含まないように指示します。

それは非常に一般的であり(しばしば義務付けられています)、誰かがそこに入れないと非常にイライラします。 shouldは、インクルードしたときに各.hファイルにヘッダーガードがあることを単純に期待できます。もちろん、あなたは物事を想定するときに彼らが言うことを知っています(「あなたと私のお尻を作る」)が、それはあなたが期待しているものでなければなりません。

2
corsiKa

Uの人々は、私が含めたいすべてのヘッダーファイルにヘッダーガードを配置する必要があることを意味します。つまり、次のようにヘッダーガードを配置する必要があるよりも、abc.hとdef.hをインクルードする次のヘッダーファイルがあります。#ifndef abc_h #defineabc_hおよび#ifndefdef_h #define def_h

1
Rashid Mirza

これはinclude guardと呼ばれ、実際、C/C++ヘッダーファイルの一般的なイディオムです。これにより、ヘッダーファイルの内容を複数回含めることなく、ヘッダーファイルを複数回インクルードできます。

名前EXAMPLE_H_は任意の規則ですが、example.hのような名前を除外するCプリプロセッサマクロの命名規則に従う必要があります。 Cマクロはすべて単一のグローバル名前空間で定義されているため、インクルードガードに同じ名前を使用する異なるヘッダーファイルがないことが重要です。したがって、通常、プロジェクトまたはライブラリの名前をインクルードガード名に含めることをお勧めします。

#ifndef __MYPROJECT_EXAMPLE_H__
...
0