獲取當前函數名 __FUNCTION__ 的使用<轉>

vs項目中見過這種獲取 當前函數名的調用。以爲挺方便的就記錄一下。程序員

==============================================================編程

轉載地址:http://blog.csdn.net/dafan/article/details/5781491數組

__FILE__
__LINE__
__DATE__
__TIME__
__FUNC__安全

 

__FUNCTION__函數

 

 

在Visual Studio 2005中,默認狀況下,此特性是激活的,但不能與/EP和/P編譯選項同時使用。請注意在IDE環境中,不能識別__func__ ,而要用__FUNCTION__ 代替。

Comeau的用戶也應使用 __FUNCTION__ ,而不是 __func__ 。

C++ BuilderX的用戶則應使用稍稍不一樣的名字:__FUNC__ 。

GCC 3.0及更高的版本同時支持 __func__ 和__FUNCTION__ 。工具

 

+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=ui

 

僅僅爲了獲取函數名,就在函數體中嵌入硬編碼的字符串,這種方法單調乏味還易致使錯誤,不如看一下怎樣使用新的C99特性,在程序運行時獲取函數名吧。 

  對象反射庫、調試工具及代碼分析器,常常會須要在運行時訪問函數的名稱,直到不久前,惟一能完成此項任務而且可移植的方法,是手工在函數體內嵌入一個帶有該函數名的硬編碼字符串,沒必要說,這種方法很是單調無奇,而且容易致使錯誤。本文將要演示怎樣使用新的C99特性,在運行時獲取函數名。

  那麼怎樣以編程的方式從當前運行的函數中獲得函數名呢?

  答案是:使用__FUNCTION__ 及相關宏。

  引出問題

  一般,在調試中最讓人心煩的階段,是不斷地檢查是否已調用了特定的函數。對此問題的解決方法,通常是添加一個cout或printf()——若是你使用C語言,以下所示:

void myfunc()
{
cout<<"myfunc()"<<endl;
//其餘代碼
}

  一般在一個典型的工程中,會包含有數千個函數,要在每一個函數中都加入一條這樣的輸出語句,無疑難過上「蜀山」啊,所以,須要有一種機制,能夠自動地完成這項操做。

  獲取函數名

  做爲一個C++程序員,可能常常遇到 __TIME__、__FILE__、__DATE__ 這樣的宏,它們會在編譯時,分別轉換爲包含編譯時間、處理的轉換單元名稱及當前時間的字符串。

  在最新的ISO C標準中,如你們所知的C99,加入了另外一個有用的、相似宏的表達式__func__,其會報告未修飾過的(也就是未裁剪過的)、正在被訪問的函數名。請注意,__func__不是一個宏,由於預處理器對此函數一無所知;相反,它是做爲一個隱式聲明的常量字符數組實現的:

static const char __func__[] = "function-name";

  在function-name處,爲實際的函數名。爲激活此特性,某些編譯器須要使用特定的編譯標誌,請查看相應的編譯器文檔,以獲取具體的資料。

  有了它,咱們可免去大多數經過手工修改,來顯示函數名的苦差事,以上的例子可以下所示進行重寫:

void myfunc()
{
cout<<"__FUNCTION__"<<endl;
}

  官方C99標準爲此目的定義的__func__標識符,確實值得你們關注,然而,ISO C++卻不徹底支持全部的C99擴展,所以,大多數的編譯器提供商都使用 __FUNCTION__ 取而代之,而 __FUNCTION__ 一般是一個定義爲 __func__ 的宏,之因此使用這個名字,是由於它已受到了大多數的普遍支持。

  在Visual Studio 2005中,默認狀況下,此特性是激活的,但不能與/EP和/P編譯選項同時使用。請注意在IDE環境中,不能識別__func__ ,而要用__FUNCTION__ 代替。

  Comeau的用戶也應使用 __FUNCTION__ ,而不是 __func__ 。

  C++ BuilderX的用戶則應使用稍稍不一樣的名字:__FUNC__ 。

  GCC 3.0及更高的版本同時支持 __func__ 和__FUNCTION__ 。

  一旦可自動獲取當前函數名,你能夠定義一個以下所示顯示任何函數名的函數:

void show_name(const char * name)
{
cout<<name<<endl;
}

void myfunc()
{
show_name(__FUNCTION__); //輸出:myfunc
}

void foo()
{
show_name(__FUNCTION__); //輸出:foo
}

  由於 __FUNCTION__ 會在函數大括號開始以後就當即初始化,因此,foo()及myfunc()函數可在參數列表中安全地使用它,而不用擔憂重載。

  簽名與修飾名

  __FUNCTION__ 特性最初是爲C語言設計的,然而,C++程序員也會常常須要有關他們函數的額外信息,在Visual Studio 2005中,還支持另外兩種非標準的擴展特性:__FUNCDNAME__ 與 __FUNCSIG__ ,其分別轉譯爲一個函數的修飾名與簽名。函數的修飾名很是有用,例如,在你想要檢查兩個編譯器是否共享一樣的ABI時,就可派得上用場,另外,它還能幫助你破解那些含義模糊的連接錯誤,甚至還可用它從一個DLL中調用另外一個用C++連接的函數。在下例中,show_name()報告了函數的修飾名:

void myfunc()
{
show_name(__FUNCDNAME__); //輸出:?myfunc@@YAXXZ
}

  一個函數的簽名由函數名、參數列表、返回類型、內含的命名空間組成。若是它是一個成員函數,它的類名和const/volatile限定符也將是簽名的一部分。如下的代碼演示了一個獨立的函數與一個const成員函數簽名間的不一樣之處,兩個函數的名稱、返回類型、參數徹底相同:

void myfunc(){show_name(__FUNCSIG__); // void __cdecl myfunc(void)}struct S{void myfunc() const {show_name(__FUNCSIG__); //void __thiscall S::myfunc(void) const}};
相關文章
相關標籤/搜索