2010-05-30 96 views
13

關於以下「模式」的最佳做法是什麼?帶#ifndef的C頭文件最佳做法#define #endif

#ifndef BLAFOO_H 
#define BLAFOO_H 
/* ... 
* ... 
*/ 
#endif /* BLAFOO_H */ 

我該如何命名#define指令中的標題?我見過所有從BLAFOO_H__BLAFOO_H_BLAFOO_H_等。

+8

僅供參考,*模式*稱爲**包括守衛**。 – 2010-05-30 17:05:46

回答

1

只要不可能在其他地方使用它並不重要。我通常會使用類似BLAFOO_H_INCLUDED的東西。

22

將它們命名爲BLAFOO_H(我個人使用BLAFOO_H_其中BLAFOO是頭文件名)。

確保您的BLAFOO不會與其他文件/庫/衝突等。您正在使用,例如讓你的項目和/或模塊名稱成爲這個名字的一部分。

_開頭的標識符爲實現/編譯器保留,所以不要使用它。

+5

+1表示以'_'開始的標識符被保留用於執行 – 2010-05-30 18:08:29

3

唯一真正的要求是它不會與另一個使用相同名稱的文件發生衝突。對於我所見過的所有項目,它通常會將項目名稱與命名空間(或文件所在的文件夾所在的文件夾)進行完全量化。有時它也包括文件的創建日期。

所以,如果你在項目ABC文件夾DEF今天的工作,那麼你可以做:

#ifndef ABC_DEF_BLAFOO_H_05_30_2010 

這是不太可能有什麼衝突。

5

我使用UUID這是我保證#define不與其他人發生衝突。我在某處看到它,並決定使用它。

我的模式是這樣的:__<filename>_H_<uuid>__

如。 #define __TYPES_H_79057761_16D6_478A_BFBC_BBF17BD3E9B9__的文件名爲types.h

+0

如何生成UUID? 您是否在IDE中使用自動化工具或功能? – 2010-05-30 17:06:45

+2

我也認爲使用GUID是一個好主意,但是有一些註釋 - 嚴格來說,不應該使用'__'前綴,因爲它是爲實現保留的(儘管很少有機會與GUID發生衝突)。另外,你很有可能會發現你的團隊中的其他人不喜歡它 - 至少這就是我發現的。在這種情況下,我不會推它,因爲我不記得一個包含警惕衝突實際上導致問題的情況。 – 2010-05-30 17:23:03

+0

@Thomas - 在Windows上,Visual Studio(和/或Windows SDK)提供了一個命令行工具uuidgen和一個GUI工具'guidgen'。我確信Unix系統有類似的工具。 – 2010-05-30 17:26:38

2

與其他C風格的問題,只是一致。沒有辦法,你會知道每個圖書館的名字空間,以後有人可能會與你的程序鏈接。爲什麼?他們中的很多人還沒有寫出:)

因此,它不是一個包括衛兵的問題,它是一個問題,首先要說明標題的名稱。

我可能會想出一些很酷的新字符串實用程序,並將其命名爲strutil。這是一個壞主意,因爲(當然)其他人已經想出了新的字符串實用程序,並將頭部命名爲相同。

所以,我的名字我的post_strutils.h和:

#ifndef POST_STRUTILS_H 
#define POST_STRUTILS_H 
/* code */ 
#endif 

我可能甚至稱之爲post_str_utils.h並確定適當包括警衛,因爲我知道,我有一個很常見的姓氏。查找名稱空間有時很困難。僅僅使用一個不能保證別人在向野外發布某些東西之前進行過搜索。儘可能地獨特。

根據某人告訴他們的編譯器搜索標題的位置,它不僅僅是名稱空間衝突,它也是文件名。盡你所能將標題命名爲唯一,然後編寫包含後衛來匹配它。有人可能想要#error,如果頭被多次包含,如果僅用於削減#include不需要的指令,使用UUID類型會造成混淆,因爲它與文件名不匹配(甚至不相似)有問題的標題。它也使得grep/awk(或類似的)動力皮棉腳本難寫。

我不是說你應該爲每個庫/模塊命名後,但要小心使公共頭文件名稱唯一。與搜索引擎的快速會議將告訴你,如果你打在一個未使用的名稱空間。請讓包含衛兵匹配(或至少非常類似)標題。同樣,一致性受到高度讚揚。從你的榜樣,我期望:

int blahfoo_init(void); 
double blahfoo_getval(blahfoo_t *blah); 

如果經過周折才找到唯一的命名空間中,一定要使用它:)

+0

對於「名稱空間」前綴+1 – 2010-05-30 18:46:17