variable 有關在C++標識符中使用下劃線的規則是什麼?




c++ underscore variable (4)

在C ++中通常使用某種前綴命名成員變量,以表示它們是成員變量,而不是局部變量或參數。 如果你來自MFC背景,你可能會使用m_foo 。 我偶爾也見過myFoo

C#(或可能只是.NET)似乎建議只使用下劃線,如_foo 。 這是由C ++標准允許的嗎?


規則(在C ++ 11中沒有改變):

  • 保留在任何範圍內,包括用作實現宏:
    • 以下劃線開頭的標識符緊跟著一個大寫字母
    • 包含相鄰下劃線(或“雙下劃線”)的標識符
  • 保留在全局名稱空間中:
    • 以下劃線開頭的標識符
  • 而且, std命名空間中的所有內容都是保留的。 (不過,您可以添加模板專業化。)

從2003年C ++標準:

17.4.3.1.2全局名稱[lib.global.names]

某些名稱和功能簽名集始終保留給實施:

  • 每個包含雙下劃線( __ )的名稱或以下劃線開頭且後面帶有大寫字母(2.11)的名稱保留給實施用於任何用途。
  • 以下劃線開頭的每個名稱都保留給實現,以用作全局名稱空間中的名稱。 165

這些名字也保留在namespace ::std (17.4.3.1)中。

由於C ++基於C標準(1.1 / 2,C ++ 03),並且C99是規範性參考(1.2 / 1,C ++ 03),所以這些標準也適用於1999 C標準:

7.1.3保留標識符

每個頭聲明或定義在其相關子條款中列出的所有標識符,並可選擇聲明或定義其相關未來庫方向子條款中列出的標識符,以及始終為任何用途或用作文件範圍標識符而保留的標識符。

  • 所有以下劃​​線和大寫字母或其他下劃線開頭的標識符總是保留用於任何用途。
  • 所有以下劃​​線開頭的標識符總是保留用作普通標籤和標籤名稱空間中具有文件範圍的標識符。
  • 如果包含任何相關標題,則下列任何子條款中的每個宏名稱(包括未來的圖書館方向)都將被保留以供指定使用; 除非另有明確說明(見7.1.4)。
  • 在下列任何子條款中(包括未來的圖書館方向),所有具有外部鏈接的標識符始終保留用作具有外部鏈接的標識符。 154
  • 每個包含以下任何子條款(包括未來庫方向)中列出的文件範圍的標識符都被保留用作宏名稱,並且如果包含任何相關頭文件,則將其用作具有相同名稱空間中的文件範圍的標識符。

沒有其他標識符被保留。 如果程序在保留的上下文中聲明或定義了一個標識符(7.1.4中允許的除外),或者將保留的標識符定義為宏名稱,則行為是未定義的。

如果程序刪除(使用#undef )上面列出的第一組中的標識符的任何宏定義,則行為未定義。

154)具有外部鏈接的保留標識符列表包括errnomath_errhandlingsetjmpva_end

其他限制可能適用。 例如,POSIX標准保留了很多可能以正常代碼顯示的標識符:

  • 以大寫字母E開頭的名稱後跟數字或大寫字母:
    • 可能會用於其他錯誤代碼名稱。
  • 以“或”開頭的名稱後跟小寫字母
    • 可用於其他字符測試和轉換功能。
  • 名稱以LC_開頭,後跟大寫字母
    • 可用於指定語言環境屬性的其他宏。
  • 所有現有數學函數的後綴名為fl都被保留
    • 用於分別對float和long double參數進行操作的相應函數。
  • SIG開頭並以大寫字母開頭的名稱將被保留
    • 獲取更多信號名稱。
  • SIG_開頭,後跟大寫字母的名稱將被保留
    • 用於額外的信號動作。
  • 名稱以strmemwcs開頭,後面跟著小寫字母
    • 用於附加的字符串和數組函數。
  • 名稱以PRISCN開頭,後面跟著任何小寫字母或X被保留
    • 用於附加格式說明符宏
  • _t結尾的名稱是保留的
    • 對於其他類型名稱。

儘管目前將這些名稱用於自己的目的可能不會導致問題,但它們確實會提高與該標準的未來版本衝突的可能性。

就我個人而言,我不會用下劃線啟動標識符。 我的規則的新增加點:不要在任何地方使用雙下劃線,這很容易,因為我很少使用下劃線。

在對本文進行研究之後,我不再用_t結束我的標識符,因為這是POSIX標准保留的。

關於以_t結尾的任何標識符的規則讓我感到驚訝。 我認為這是一個POSIX標準(尚不確定)尋求澄清和正式章節和詩句。 這是來自GNU libtool手冊 ,列出了保留的名稱。

CesarB提供了以下指向opengroup.org/onlinepubs/009695399/functions/xsh_chap02_02.html保留符號的鏈接,並指出“許多其他保留的前綴和後綴......可以在那裡找到”。 這裡定義了POSIX 2008保留的符號。 這些限制比上述限制稍微有點微妙。


避免名稱衝突的規則都在C ++標準中(參見Stroustrup書),並由C ++大師(Sutter等)提及。

個人規則

因為我不想處理案件,並且想要一個簡單的規則,所以我設計了一個既簡單又正確的個人規則:

命名符號時,如果您符合以下條件,您將避免與編譯器/ OS /標準庫衝突:

  • 永遠不要用下劃線開始符號
  • 永遠不要在內部使用兩個連續的下劃線來命名符號。

當然,將你的代碼放在一個唯一的命名空間中也有助於避免碰撞(但不會防止惡意的宏)

一些例子

(我使用的宏是因為它們是C / C ++符號的更多代碼污染,但它可以是從變量名到類名的任何東西)

#define _WRONG
#define __WRONG_AGAIN
#define RIGHT_
#define WRONG__WRONG
#define RIGHT_RIGHT
#define RIGHT_x_RIGHT

從C ++ 0x草案中提取

n3242.pdf文件(我期望最終的標准文本是相似的):

17.6.3.3.2全局名稱[global.names]

某些名稱和功能簽名集始終保留給實施:

- 包含雙下劃線_ _的每個名稱或以下劃線開頭且後跟大寫字母(2.12)的內容保留給實施用於任何用途。

- 以下劃線開頭的每個名稱都保留給實現,以用作全局名稱空間中的名稱。

但也:

17.6.3.3.5用戶定義的文字後綴[usrlit.suffix]

不以下劃線開頭的文字後綴標識符被保留用於將來的標準化。

這最後一個條款是令人困惑的,除非你認為如果沒有在全局命名空間中定義,那麼以一個下劃線開頭並且後面跟一個小寫字母的名稱將是OK。


是的,下劃線可以在標識符的任何地方使用。 我相信這些規則是:第一個字符中的az,AZ,_以及後面的字符都是+ 0-9。

下劃線前綴在C代碼中很常見 - 單個下劃線表示“私有”,雙下劃線通常保留供編譯器使用。


至於問題的另一部分,通常將下劃線放在變量名的末尾 ,以免與內部任何事物發生衝突。

我甚至在類和名字空間中這樣做,因為我只需要記住一條規則(與“在全局範圍內的名稱末尾和其他地方的名稱的開頭”相比較)。





c++-faq