當(dāng)前位置:
首頁(yè) >
在C语言中以编程的方式获取函数名
發(fā)布時(shí)間:2025/3/15
44
豆豆
生活随笔
收集整理的這篇文章主要介紹了
在C语言中以编程的方式获取函数名
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
在C語(yǔ)言中以編程的方式獲取函數(shù)名
僅僅為了獲取函數(shù)名,就在函數(shù)體中嵌入硬編碼的字符串,這種方法單調(diào)乏味還易導(dǎo)致錯(cuò)誤,不如看一下怎樣使用新的C99特性,在程序運(yùn)行時(shí)獲取函數(shù)名吧。對(duì)象反射庫(kù)、調(diào)試工具及代碼分析器,經(jīng)常會(huì)需要在運(yùn)行時(shí)訪問(wèn)函數(shù)的名稱,直到不久前,唯一能完成此項(xiàng)任務(wù)并且可移植的方法,是手工在函數(shù)體內(nèi)嵌入一個(gè)帶有該函數(shù)名的硬編碼字符串,不必說(shuō),這種方法非常單調(diào)無(wú)奇,并且輕易導(dǎo)致錯(cuò)誤。本文將要演示怎樣使用新的C99特性,在運(yùn)行時(shí)獲取函數(shù)名。
那么怎樣以編程的方式從當(dāng)前運(yùn)行的函數(shù)中得到函數(shù)名呢?
答案是:使用__FUNCTION__ 及相關(guān)宏。
引出問(wèn)題
通常,在調(diào)試中最讓人心煩的階段,是不斷地檢查是否已調(diào)用了特定的函數(shù)。對(duì)此問(wèn)題的解決方法,一般是添加一個(gè)cout或printf()——假如你使用C語(yǔ)言,如下所示:
void myfunc()
{
cout<<"myfunc()"<<endl;
//其他代碼
}
通常在一個(gè)典型的工程中,會(huì)包含有數(shù)千個(gè)函數(shù),要在每個(gè)函數(shù)中都加入一條這樣的輸出語(yǔ)句,無(wú)疑難過(guò)上“蜀山”啊,因此,需要有一種機(jī)制,可以自動(dòng)地完成這項(xiàng)操作。
獲取函數(shù)名
作為一個(gè)C++程序員,可能經(jīng)常碰到 __TIME__、__FILE__、__DATE__ 這樣的宏,它們會(huì)在編譯時(shí),分別轉(zhuǎn)換為包含編譯時(shí)間、處理的轉(zhuǎn)換單元名稱及當(dāng)前時(shí)間的字符串。
在最新的ISO C標(biāo)準(zhǔn)中,如大家所知的C99,加入了另一個(gè)有用的、類似宏的表達(dá)式__func__,其會(huì)報(bào)告未修飾過(guò)的(也就是未裁剪過(guò)的)、正在被訪問(wèn)的函數(shù)名。請(qǐng)注重,__func__不是一個(gè)宏,因?yàn)轭A(yù)處理器對(duì)此函數(shù)一無(wú)所知;相反,它是作為一個(gè)隱式聲明的常量字符數(shù)組實(shí)現(xiàn)的:
static const char __func__[] = "function-name";
在function-name處,為實(shí)際的函數(shù)名。為激活此特性,某些編譯器需要使用特定的編譯標(biāo)志,請(qǐng)查看相應(yīng)的編譯器文檔,以獲取具體的資料。
有了它,我們可免去大多數(shù)通過(guò)手工修改,來(lái)顯示函數(shù)名的苦差事,以上的例子可如下所示進(jìn)行重寫:
void myfunc()
{
cout<<"__FUNCTION__"<<endl;
}
官方C99標(biāo)準(zhǔn)為此目的定義的__func__標(biāo)識(shí)符,確實(shí)值得大家關(guān)注,然而,ISO C++卻不完全支持所有的C99擴(kuò)展,因此,大多數(shù)的編譯器提供商都使用 __FUNCTION__ 取而代之,而 __FUNCTION__ 通常是一個(gè)定義為 __func__ 的宏,之所以使用這個(gè)名字,是因?yàn)樗咽艿搅舜蠖鄶?shù)的廣泛支持。
在Visual Studio 2005中,默認(rèn)情況下,此特性是激活的,但不能與/EP和/P編譯選項(xiàng)同時(shí)使用。請(qǐng)注重在IDE環(huán)境中,不能識(shí)別__func__ ,而要用__FUNCTION__ 代替。
Comeau的用戶也應(yīng)使用 __FUNCTION__ ,而不是 __func__ 。
C++ BuilderX的用戶則應(yīng)使用稍稍不同的名字:__FUNC__ 。
GCC 3.0及更高的版本同時(shí)支持 __func__ 和__FUNCTION__ 。
一旦可自動(dòng)獲取當(dāng)前函數(shù)名,你可以定義一個(gè)如下所示顯示任何函數(shù)名的函數(shù):
void show_name(const char * name)
{
cout<<name<<endl;
}
void myfunc()
{
show_name(__FUNCTION__); //輸出:myfunc
}
void foo()
{
show_name(__FUNCTION__); //輸出:foo
}
因?yàn)?__FUNCTION__ 會(huì)在函數(shù)大括號(hào)開始之后就立即初始化,所以,foo()及myfunc()函數(shù)可在參數(shù)列表中安全地使用它,而不用擔(dān)心重載。
簽名與修飾名
__FUNCTION__ 特性最初是為C語(yǔ)言設(shè)計(jì)的,然而,C++程序員也會(huì)經(jīng)常需要有關(guān)他們函數(shù)的額外信息,在Visual Studio 2005中,還支持另外兩種非標(biāo)準(zhǔn)的擴(kuò)展特性:__FUNCDNAME__ 與 __FUNCSIG__ ,其分別轉(zhuǎn)譯為一個(gè)函數(shù)的修飾名與簽名。函數(shù)的修飾名非常有用,例如,在你想要檢查兩個(gè)編譯器是否共享同樣的ABI時(shí),就可派得上用場(chǎng),另外,它還能幫助你破解那些含義模糊的鏈接錯(cuò)誤,甚至還可用它從一個(gè)DLL中調(diào)用另一個(gè)用C++鏈接的函數(shù)。在下例中,show_name()報(bào)告了函數(shù)的修飾名:
void myfunc()
{
show_name(__FUNCDNAME__); //輸出:?myfunc@@YAXXZ
}
一個(gè)函數(shù)的簽名由函數(shù)名、參數(shù)列表、返回類型、內(nèi)含的命名空間組成。假如它是一個(gè)成員函數(shù),它的類名和const/volatile限定符也將是簽名的一部分。以下的代碼演示了一個(gè)獨(dú)立的函數(shù)與一個(gè)const成員函數(shù)簽名間的不同之處,兩個(gè)函數(shù)的名稱、返回類型、參數(shù)完全相同:
void myfunc()
{
show_name(__FUNCSIG__); // void __cdecl myfunc(void)
}
strUCt S
{
void myfunc() const
{
show_name(__FUNCSIG__); //void __thiscall S::myfunc(void) const
}
};
總結(jié)
以上是生活随笔為你收集整理的在C语言中以编程的方式获取函数名的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 今天的春天到了的p2psearcher
- 下一篇: MFC类中获得其它类指针