2012-04-09 32 views
7

私は現在CSコースの最終試験のために勉強していますが、C++ #ifndefの構文に関するマイナーな(おそらくメジャーな)問題にぶつかってきました。#ifndef C++のインクルードガードの構文

の#includeガードとして、それを使用しているとき、私は#infndefするための構文を見てきましたし、ウェブ上で最もが言うように見える:

#ifndef HEADER_H 
#define "header.h" 
... 
#endif 

をしかし、私のクラスのチュートリアルのスライドのように例を示します。

#ifndef __HEADER_H__ 
#define "header.h" 
... 
#endif 

2つの違いが何であれ(もしあれば)、私は不思議に思っていました。試験ではおそらく#includeガードを書くように求められますが、私は従来の知恵は教授/教員の言うこととちょうど合っていることを知っていますが、編集中に違いがある場合は知りたいと思います。

+5

あなたの家庭教師のルールが壊れていることについての議論については、[ここ](http://stackoverflow.com/questions/228783)を参照してください。[here](http://stackoverflow.com/questions/3345159)あなたがそれらを壊すなら、何がうまくいかないかもしれないかの例また、ガードをヘッダーの内側に入れる*。 –

+0

そのままですが、インラインコードは意味をなさない:文字列リテラルを '#define 'することはできない。あなたは '#include" header.h "(元の言い回し)または' #define HEADER_H'(通常はヘッダプリアンブルの中に入るもの)を意味しましたか? – Attila

答えて

17

通常の習慣は、どちらも実行しないで、反復を減らすので、インクルードガードの内部にのヘッダーファイルを入れます。例えば:

がheader.h

#ifndef HEADER_H 
#define HEADER_H 

// Rest of header file contents go here 

#endif 

正確に何をマクロ名として使用すると、ダウンあなたの特定のコーディング標準にあります。しかし、CおよびC++標準には、アンダースコアで始まる識別子であるを使用できないようにするためのさまざまな微妙な規則がありますので、安全な側にあるように__HEADER_H__を避けてください。

コードベース内の他のものと衝突する可能性のあるものを選択する必要があることにも言及する価値があります。たとえば、他の場所でHEADER_Hという変数を使用したことがあった場合(おそらく、実現している)、怒っているエラーが発生します。


1。 C99規格のセクション7.1.3。

+1

...実装ヘッダーファイルでない場合は、アンダースコアの後にアンダースコアまたは大文字を含む識別子は使用しないでください。 –

+0

@JerryCoffin: "containing"、または "starting with"? –

+0

Cの場合、開始します。 C++の場合、倍精度のアンダースコアを含むこともできますが(アンダースコアとそれに続くキャップは、最初でない限り許されます)。 –

1

変数名にアンダースコアを使用しない場合は違いはありませんが、命名規則にすぎません。

ユニークなものを入力するだけです。

+4

本当ではありません。 2つのアンダースコアで始まる名前は、実装のために予約されています(C99では、少なくとも)。 –

+1

+1:実際には、「通常の」やり方を述べるのではなく、OPの質問に答えます。 –

+4

それは単なる慣習ではありません。 '__'で始まる識別子を使用すると、コードの動作が未定義になります。実装(コンパイラまたは標準ライブラリのいずれか)は、独自の目的で '__HEADER_H__'という名前を自由に使用できます。それがそうであるなら、あなた自身のその識別子の使用は、文字通り*何でも*意味することができます。 –

5

二重のアンダースコアで始まる名前は実装用に予約されていますので、インクルードガードで__SOMETHINGを使用することをお勧めします。また、衝突を起こしにくい名前を選んでみてください。だから、あなたのクラスのチュートリアルは少なくとも2つのカウントで間違っているようです。たとえばhumorous articleを参照してください。

0

ヘッダー自体ではなく、ヘッダーを含むファイルにインクルードガードを配置する引数は、ファイルが既に含まれている場合、コンパイラ(特にプリプロセッサ)が開いて読み込む必要がないことですインクルードファイルを再度作成します。

これは弱い議論です。実際には、時間が節約され、エラーの可能性が大きくなります。あなたの例では

#ifndef HEADER_H 
#include "header.h" 
... 
#endif 

あなたは私たちに#define HEADER_Hを示していません。それはheader.hのどこかですか?もしそうなら、header.hの作成者がインクルードガードマクロの名前としてHEADER_Hを使用することを選択したことをどうやって知っていますか?後で別のものに変わるとどうなりますか?

あなたがそこにマクロとしても定義する必要があり、インクルードを含むファイルでガードを含める置くことにした場合:他の回答は、すでにそれは入れてずっとましだ、と述べてきたように、

#ifndef HEADER_H 
#include "header.h" 
#define HEADER_H 
#endif 

をしかし、

がheader.h:

#ifndef HEADER_H 
#define HEADER_H 
/* contents of header.h */ 
#endif 

ヘッダ自体にガードインクルードには次の情報が含まれています: