各 .h ファイルが #ifndef #define #endif で始まるのはなぜですか? これらのディレクティブがなくてもプログラムをコンパイルできます。
5 に答える
いわゆる「インクルードガード」です。目的は、ファイルが複数回含まれている場合に、ファイルを複数回解析する必要がないようにすることです。
1 つのファイルが複数含まれるのを防ぎます。を使用して同じことができます
#pragma once
ディレクティブですが、これらの #ifndefs は標準であるため、すべてのコンパイラでサポートされています。
これはインクルード ガードと呼ばれます。大規模なプログラムの作成を開始し、同じ .h ファイルを .c ファイルから直接的または間接的に複数回インクルードする必要があることがわかるまでは、それらを使用せずに記述できます。次に、インクルード ガードがないと、複数の定義エラーが発生しますが、それらを使用すると、ヘッダー ファイルの内容が 1 回だけ解析され、それ以降はすべてスキップされるため、これらのエラーが回避されます。常に使用することをお勧めします。
私の理解が正しければ、インクルード ガードがない場合に、ヘッダー ファイルを複数回インクルードするとエラーや危険な動作が発生する可能性があるかどうかを知りたいと思われます。これは、複数の定義などを除外した後です。
ヘッダー ファイルにインクルード ガードがない悪意のあるプログラマーを想像してみてください。彼のヘッダー ファイルはSZ
、静的に割り当てられた配列に使用するサイズである 1 つのマクロを定義します。プログラマーは、ヘッダー ファイルを次のように記述できます。
#ifndef SZ
#define SZ 1024
#else
#if SZ == 1024
#undef SZ
#define SZ 128
#else
#error "You can include me no more than two times!"
#endif
#endif
ここで、ヘッダー ファイルを 1 回インクルードするSZ
と、1024 になります。2 回インクルードすると、SZ
128 になります。もちろん、現実世界のプログラマのほとんどは悪意を持っているわけではなく、実際に上記のようなコードを書く人はいません。
C 標準では、 のインクルード時に が定義されているかどうかに応じて、異なる動作で d を複数回使用できることassert.h
に注意してください。したがって、ガードを含めることはできません。ただし、これはバグではなく機能です。#include
NDEBUG
assert.h
assert.h
ヘッダーファイルに次のような定義が含まれている場合
int i;よりも、ガードなしで数回インクルードすると、コンパイル エラーが発生します。
ifndef は、一部のプリプロセッサ変数が定義されていないことを確認し (初めて定義されていません)、再度キャプチャされるのを避けるために明示的に定義します。MSVCでは、使用することもできます
#pragma onceの代わりに
ifndef
。