2010-09-26 38 views
2

我不知道爲什麼#ifndef指令後面的名稱總是全部大寫,並且看起來不匹配實際頭文件的名稱?圍繞這個的規則是什麼?我一直在尋找網絡,但是,我還沒有找到任何解釋。如果我的頭文件命名爲myheader.h將它,然後即可使用:C++ #ifndef用於包含文件,爲什麼所有頭文件都用於頭文件?

#ifndef MYHEADER 

如果是這樣,爲什麼?規則是什麼?

回答

6

這些預定義和有沒有這樣的規定。 (只要它們在報頭匹配#defines

然而,慣例是使用全大寫爲預處理器符號。

+0

謝謝!當然!現在對我來說很明顯,不知道爲什麼我之前沒有碰到過。它在ifndef之後定義如此..哈,謝謝! – foo 2010-09-26 19:49:00

0

你可以使用任何你想要的名字,但你想讓它唯一的,這樣的值將不是你的頭以任何機會之外定義,因此使用標頭名稱以大寫只是爲了確保一個很好的約定。

+0

謝謝,現在已經很清楚了。 – foo 2010-09-26 19:53:01

1

它不要求全部大寫。這只是常見的慣例。我通常使用類似#ifndef MYHEADER_H_INCLUDED

+0

謝謝,它終於爲我點了。我只是沒有看到(奇怪),該定義是在ifndef之後。我以某種方式看着錯誤的地方,認爲文件名將被解析爲全部大寫ifndef。 – foo 2010-09-26 19:51:14

1

谷歌爲include guard找到東西實際上是關於什麼的。

關於全大寫的:這是一個約定爲宏在全大寫。原因是宏是由預處理器處理的,這是一種神祕的文本處理工具,它對C++一無所知,並且最好不要使用公共標識符,以免它踐踏整個系統,造成一團糟。

+0

是的,我意識到常量的慣例。但不知何故錯過了#ifndef之後的#define。 – foo 2010-09-26 19:52:19

6

有沒有「規則」,也有隻是約定。第一個也是最常用的約定是所有的預編譯器宏都是大寫的,所以標頭守衛也應該全部大寫。

至於宏名稱,我使用的是什麼(以及我見過的大多數代碼使用的)只是標題的名稱(如所述,轉爲全部大寫),包括擴展名,用點下劃線,然後是_INCLUDED

#ifndef MYHEADER_HPP_INCLUDED 
#define MYHEADER_HPP_INCLUDED 
// ... 
#endif 

注意,開始以單下劃線後面是許多在前面加上這樣的標識符以下劃線或雙下劃線,但它不是好的做法,因爲標準規定的標識符開始(或含)雙下劃線和那些大寫字母保留給所有範圍的編譯器/庫特定的東西(例如VC++中的__declspec或標準頭中使用的宏);所有以單個下劃線開頭的其他標識符都保留在全局範圍內。所以不應該使用這種標識符來避免衝突。

關於這個東西的更多信息here

1

這樣做是爲了確保你的頭文件生成過程中是隻讀一次。實現這個成語是結構:

#ifndef _SOME_UNIQUE_NAME 
    #define _SOME_UNIQUE_NAME 
    /* The actual header code */ 
    #endif 

這意味着你應該選擇你非常肯定將是唯一的一個名字,是的#ifndef有效的標識符。您還應該確保該標識符未在實際代碼中使用,或與變量或其他內容混淆。有一個大寫的標記清楚地標記成語。除此之外,這只是慣例而非語言決定的選擇。 Visual Studio的嚮導生成一個類似標識符的GUID。 Sone編譯器支持#pragma一次具有相同的效果。

+1

避免在標頭警衛中留下下劃線(並且,一般來說,對於標識符,後跟一個大寫字母);詳情請參閱我的答案。 – 2010-09-26 21:11:32

0

這是完全主觀的,除了那些通常與命名預處理器宏的字符集關聯的規則外,沒有強制規則。宏定義爲大寫是常規的。這有助於他們在源代碼中脫穎而出。我傾向於遵循的約定是文件名的嚴格大寫版本,週期由下劃線和前後下劃線替換。因此,對於一個名爲DataTableNameMangler.hpp了包括後衛看起來像:

#ifndef _DATATABLENAMEMANGLER_HPP_ 
#define _DATATABLENAMEMANGLER_HPP_ 

... 

#endif // _DATATABLENAMEMANGLER_HPP_ 

有這個,雖然我強烈建議的一致性,這個名字的文件名完全匹配沒有很大的理由。我通常使用一個小班創建者腳本來生成我的初始班級。下面的代碼片段猛砸給出了一個想法:

#!/bin/bash 
INC_GUARD_NAME="_${1^^*}_HPP_" 
echo "#ifndef $INC_GUARD_NAME" 
echo "#ifndef $INC_GUARD_NAME" 
echo 
echo "class $1 {};" 
echo 
echo "#endif // $INC_GUARD_NAME" 

這樣:

$ ./makeclass.bash DataTableNameMangler 
#ifndef _DATATABLENAMEMANGLER_HPP_ 
#ifndef _DATATABLENAMEMANGLER_HPP_ 

class DataTableNameMangler {}; 

#endif // _DATATABLENAMEMANGLER_HPP_ 

這自然只是一個非常簡單的例子。重要的是,請記住在最後一行的警衛姓名前加上註釋。 #endif不接受任何參數,因此宏將傳遞給C++編譯器,如果它未被評論,它將會抱怨它。

+2

避免在標頭警衛中使用下劃線(一般來說,對於標識符,後跟一個大寫字母);詳情請參閱我的答案。 – 2010-09-26 21:12:26