2010-05-11 91 views
14

在eclipse中,無論何時創建一個新的C++類或頭文件,我都會得到以下類型的結構。說我創建的頭文件example.h文件,我得到這個:針對C/C++代碼的預處理指令#ifndef

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

我覺得IFNDEF是說,如果沒有定義EXAMPLE_H_,定義它,這可能取決於你使用的編譯什麼工具有用,鏈接您的項目。但是,我有兩個問題:

  1. 這是相當常見的嗎?我不常看到它。使用該標題是一個好主意,還是應該直接跳到定義代碼的位置。

  2. 什麼是EXAMPLE_H_?爲什麼不是example.h,或者僅僅是例子?有沒有什麼特別的,或者可能只是一個人工製品如何偏愛自動構建項目?

+0

注意,一切都在IFNDEF與ENDIF之間,在任何情況下,你作爲一個應用程序員很可能會遇到。所以並不僅僅是#define被定義和包含一次,而是一切只被定義和包含一次。 – 2010-05-11 16:25:52

+0

好點,抱歉沒有更明確地表示,謝謝。 – 2010-05-11 19:17:25

回答

13

這是一個常見的構造。意圖是隻將頭文件的內容包含在翻譯單元中一次,即使物理頭文件包含多次。例如,如果您將標題直接包含在源文件中,並且它也通過另一個標頭間接包含,則可能會發生這種情況。

在內容周圍放置#ifndef包裝意味着編譯器只解析一次頭部的內容,並避免重新定義錯誤。

有些編譯器允許「#pragma once」做同樣的事情,但是#ifndef構造可以在任何地方工作。

+0

啊,好吧,所以你#define語句只是在那裏來定義一些東西,我可以在兩種情況下將EXAMPLE_H_替換爲FOO_BAR_,它仍然可以工作,它只是更好使用EXAMPLE_H_,因爲與命名空間衝突的可能性相比,如果我給它任何其他名稱的話,它的可能性要小得多。 – 2010-05-11 16:04:54

+0

正確的是,人們通常使用帶有下劃線的標題名稱作爲標識符中無效的字符。使用可能衝突的常見名稱擊敗目的:) – user308405 2010-05-11 16:07:11

+0

@Leif Andersen:像例子這樣的常見名稱可能會發生衝突。就我個人而言,我用全名命名空間加上文件名稱,因爲這不太可能發生衝突。我看到其他人生成完整的GUID以避免衝突的可能性。 – 2010-05-11 16:53:54

4

這只是保護您的包含的一種常見方式 - 以這種方式防止代碼被包含兩次。而且使用的標識符可以是任何東西,只是按照所述的方式進行約定。

2

請務必在頭文件的頂部執行此操作。它通常被稱爲頭球后衛或包括後衛。

它的作用是這樣的,如果一個頭文件將包含多次,它將只包含一次。如果你不這樣做,那麼你最終會遇到有關多次定義事情的錯誤以及類似的事情。

確切的定義並不重要,但通常它是文件名的一些變化。基本上,你正在檢查給定的宏是否已被定義。如果沒有,則定義它並繼續包含文件。如果有,那麼你以前必須包含該文件,並忽略該文件的其餘部分。

2

這是一名包括警衛。它保證包含標題不超過一次。

例如,如果你要:

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

第一次被包括在報頭,EXAMPLE_H_不會被定義和將被輸入的,如果塊。 EXAMPLE_H_然後由#define指令定義,並對頭的內容進行評估。

第二次包含標題時,EXAMPLE_H_已被定義,所以if塊不會被重新輸入。

這對確保您不違反一個定義規則至關重要。如果你在一個沒有包含防護的頭文件中定義了一個類,並且將這個頭文件包含了兩次,那麼由於違反了一個定義規則(這個類將被定義兩次),你會得到編譯錯誤。

雖然上面的例子很簡單,你可以很容易地看到你包含example.h兩次,經常頭包括其他頭,它並不那麼明顯。

+0

不,它不!它保證包含它不僅僅是一次:-) – Vicky 2010-05-11 16:00:13

4

這是常見的嗎?是的 - 全部 C和C++頭文件應該像這樣構造。EXAMPLE_H是一個頭部防護,它可以防止頭部中的代碼被多次包含在同一個翻譯單元中,這會導致多重定義錯誤。選擇名稱EXAPMLE_H以匹配它所守護的頭文件的名稱 - 它在項目中必須是唯一的,也可以是全局的。爲了儘量保證這一點,這是正常的前綴或您的項目名稱後綴是:

#define MYPROJ_EXAMPLE_H 

例如,如果你的項目被稱爲「的Myproj」。不要試圖認爲帶有下劃線的前綴會奇蹟般地使它變得獨一無二,像_EXAMPLE_H___EXAMPLE_H__之類的名稱是非法的,因爲它們是爲語言實現保留的。

0

這被稱爲「包含守衛」,並且確實是C/C++頭文件的常見成語。這允許多次包含頭文件,而不用包含其內容。

名稱EXAMPLE_H_是一個任意約定,但必須遵守C預處理器宏的命名規則,該規則不包括像example.h這樣的名稱。由於C宏全部在單個全局名稱空間中定義,所以重要的是您沒有不同的頭文件,它們的包含守護程序使用相同的名稱。因此,它通常是一個好主意,包括您在包括後衛名稱項目或庫的名稱:

#ifndef __MYPROJECT_EXAMPLE_H__ 
... 
+3

除了以下劃線開頭的名字後跟一個大寫字母或其他下劃線被保留給實現(即,不要用下劃線開始您的包含保護名稱)。 – 2010-05-11 16:05:33

+0

@James以及任何包含連續兩個下劃線的標識符(即不只是在開始處)。換句話說,這個答案充滿了違規。 ;) – 2010-05-11 16:24:21

2

考慮這個

foo.c文件:

#include foo.h 
#include bar.h 

文件吧.H

#include <iostream> 
#include foo.h 

現在,當我們編譯foo.c的,我們有foo.h中在那裏的兩倍!我們絕對不想這樣做,因爲所有的函數都會在第二次拋出編譯錯誤。

爲了防止發生這種情況,我們將INCLUDE GUARD置於頂端。這樣,如果它已經包含在內,我們定義一個預處理器變量,告訴我們不要再包含它。

這是非常普遍的(通常是強制性的),並且如果有人不把它放在那裏非常沮喪。你should能夠簡單地期望每個.h文件有一個頭後衛,當你包括在內。當然,你知道他們說什麼,當你承擔的事情(「讓你和我屁股」),但這應該是你期待看到的東西。

1

U人的意思是我必須爲每個頭文件放置頭文件,我想包括在內。 我,我..我有以下頭文件包含abc.h和def。^ h比我將頁眉後衛如下 的#ifndef abc_h 的#define abc_h和 的#ifndef def_h 的#define def_h