1. 程式人生 > >在C語言中以程式設計的方式獲取函式名

在C語言中以程式設計的方式獲取函式名

  在C語言中以程式設計的方式獲取函式名 僅僅為了獲取函式名,就在函式體中嵌入硬編碼的字串,這種方法單調乏味還易導致錯誤,不如看一下怎樣使用新的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__); //輸出:[email protected]@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  } };  

相關推薦

C語言程式設計方式獲取函式

  在C語言中以程式設計的方式獲取函式名 僅僅為了獲取函式名,就在函式體中嵌入硬編碼的字串,這種方法單調乏味還易導致錯誤,不如看一下怎樣使用新的C99特性,在程式執行時獲取函式名吧。 物件反射庫、除錯工具及程式碼分析器,經常會需要在執行時訪問函式的名稱,直到不久前,唯

C語言的輸入方式

讀取 緩沖區 lock 回車 scanf() spa sdn enter 回車符 在c語言中,有gets()、scanf()、getchar()等輸入方式,但是不同的方式處理的方式不同。 scanf()讀取時遇見tab、space、enter時會結束讀取,不會舍棄最後的回車

c語言關於變長引數函式的原理

     printf函式是在串列埠資訊列印中和串列埠命令列介面功能實現中經常用的函式。呼叫方式一般是這樣子的printf("cmd =%s\r\rn", cmd_str),printf("vol=%dmV, current=%dmA.", vol,current)

C語言面向物件程式設計:虛擬函式與多型(3)

 在《 C++ 程式設計思想》一書中對虛擬函式的實現機制有詳細的描述,一般的編譯器通過虛擬函式表,在編譯時插入一段隱藏的程式碼,儲存型別資訊和虛擬函式地址,而在呼叫時,這段隱藏的程式碼可以找到和實際物件一致的虛擬函式實現。     我們在這裡提供

C語言的結構體內嵌函式

1.內嵌函式定義舉例:經過真實測試         在函式中宣告定義結構體 #include "fun_in_struct.h"int main(int argc, char **argv) { //定義結構體指標或者結構體變數,分別用->和

C語言求字串長度的函式my_strlen()的幾種實現方法

C語言中求字串長度的函式的幾種實現方法 1.最常用的方法是建立一個計數器,判斷是否遇到‘\0’,不是’\0’指標就往後加一。 int my_strlen(const char *str) { assert(str != NULL);//此句判段str是否為空指標(事實上這條語

C語言二進位制方式列印資料

程式碼: #include <stdio.h> #include <string.h> #include <stdlib.h> void decToBin(int num) { if(num>0) { decToBin(num/2);

c語言自定義了一個函式,在main呼叫時提示找不到識別符號

解決方案一: 把定義的函式放在,main函式之前。 void f() { printf("Hello"); } main() { f(); } 解決方案二: 在main函式之前宣告。 void f(); main() { f

【linux CC語言常用的幾個函式的總結【一】

1、memset函式 定義變數時一定要進行初始化,尤其是陣列和結構體這種佔用記憶體大的資料結構。在使用陣列的時候經常因為沒有初始化而產生“燙燙燙燙燙燙”這樣的野值,俗稱“亂碼”。每種型別的變數都有各自的初始化方法,memset() 函式可以說是初始化記憶體的“萬能函式”,通常為新申請的記憶體進行初始化工作。

【linux CC語言常用的幾個函式的總結【二】

3、fgets 雖然用 gets() 時有空格也可以直接輸入,但是 gets() 有一個非常大的缺陷,即它不檢查預留儲存區是否能夠容納實際輸入的資料,換句話說,如果輸入的字元數目大於陣列的長度,gets 無法檢測到這個問題,就會發生記憶體越界,所以程式設計時建議使用 fgets()。fgets() 的原型為

C語言兩個反正切函式atan與atan2的區別

我們可以使用正切操作將角度轉變為斜率,那麼怎樣利用斜率來轉換為角度呢?可以利用斜率的反正切函式將他轉換為相應的角度.as中有兩個函式可以計算反正切,我們來看一下. 1、as中Math.atan() Math.atan()接受一個引數:用法如下: angel=Math.atan(slope)  angel為一

在 Excel 程式設計方式複製工作表會導致執行時錯誤 1004

建立一個新的工作簿,然後保留一個工作表並刪除其他所有工作表。設定該工作簿的格式,然後新增模板必須預設包含的所有文字、資料和圖表。單擊“Microsoft Office 按鈕”,然後單擊“另存為”。在“檔名”框中,鍵入所需的 Excel 模板名稱。在“儲存型別”列表中,單擊“模板 (*.xltx)”,然後單擊“

C語言常用的檔案操作函式

C函式庫中檔案操作函式: (1)fopen:開啟檔案 函式原型:FILE* fopen(char *path, char *mode); 函式引數:path----開啟檔名及其路徑      mode----r w a …… 函式返回:成功則返回指向該流的檔案指標,失敗則返回NULL並把錯誤存在errno中

如何在 VB 程式設計方式建立並呼叫 Excel 巨集

1. 在 Visual Basic 中建立一個標準 EXE 專案。預設情況下會建立 Form1。 2. 單擊“專案”選單中的“引用”,然後選中“Microsoft Visual Basic for Applic

c語言結構體在子函式的用法

在c語言中,結構體是一種很常用的資料結構,但是要用好卻又有許多疑惑。 假設下面這個是我們要用到的結構體 typedef struct DATA data; struct DATA{ int *A; data *next; data *last; } 首先來看一下這兩個句子

C語言利用封裝好的函式實現英文字母的大小寫轉換

在C語言中,利用tolower和toupper兩個函式實現英文字母的大小寫之間的轉換 範例1:將s字串內的小寫字母轉換成大寫字母 #include <ctype.h> int main(

c語言的二級指標做函式引數

1.用指標做函式引數申請動態記憶體的問題 //如果函式引數是指標,不能用一級指標做函式引數實現申請動態記憶體 void getMemory(char *p, int num) { p = (char *)malloc(sizeof(char)*num); } void

C語言如何將陣列作為函式引數傳遞

今天覆習到c語言的陣列,看到這麼一個問題: 現在,你的程式要讀入兩個多項式,然後輸出這兩個多項式的和,也就是把對應的冪上的係數相加然後輸出。 程式要處理的冪最大為100。 輸入格式: 總共要輸入兩個多項式,每個多項式的輸入格式如下: 每行輸入兩個數字,第一個表

C語言字符串形式輸出枚舉變量

main rfi tin port src sample .com com box C語言中以字符串形式輸出枚舉變量 摘自:https://blog.csdn.net/haifeilang/article/details/41079255 2014年

9、C語言二維陣列及陣列及指向二維陣列的指標變數

#include <stdio.h> #include <stdlib.h> //與二維陣列相關的指標變數([] 比 *優先順序高) //在一般指標變數指向二維陣列,或者n維陣列,要直接操作a[i][j],對指標的操作必須有兩個符號(其中不出現&,如果有&則相應的加