2013-05-28 26 views
-1

據我所知,預定義的標識符__func__使功能名稱可在該功能中使用。但是我什麼時候需要它?其中一個目的可以用於調試。其他用例是什麼?C,C++中__func__標識符的用例?

+11

調試不是一個足夠好的用例嗎? – jamesdlin

+1

是的。但僅僅爲了知識的目的,我想知道更多。 – akshay

+0

我認爲這是標識符的唯一真正目的。出於任何其他目的(例如反思?),語言中可能會有更好的設施。 – 2013-05-28 05:36:08

回答

7

更新:爲了清楚起見,因爲在(便攜式)C或C++有什麼可以與當前功能爲「串」(char陣列)的名字呢,你幾乎僅限於書面字符串在某處 - 可以將其全部視爲診斷或「調試」目的。說了這麼多,你可能會想出一些用於函數名稱的用法。例如,聲明性安全性,可配置日誌記錄(儘管這是「再次診斷」等)。

事實上,網絡上的大多數說明和手冊都明確指出,__func__和(__LINE____FILE__就此而言)的用途是調試和診斷。

就我個人而言,我認爲它提供了幫助使「更好」assert()輸出成爲可能。


只要你以「編程方式」需要知道當前函數的名稱,就可以使用它。幾乎所有的都不包括調試器,在調試器中已經有可用的調試器的名稱(甚至是上下文)。

__func__(或它的舊的,非標準的前身__FUNCTION__)通常與__LINE__和也許__FILE__宏一起使用,以提供跟蹤或診斷輸出的功能,即自動包括當前函數(和文件,線)。

#define TRACE(s) \ 
     do { fprintf(stderr, "%s:%d:%s: %s", __FILE__, __LINE__, __func__, (s)); \ 
     } while (0) 

然後,您可以使用它像這樣:

int my_func(char* arg1, int arg2) 
{ 
    TRACE("Doing stuff..."); 

    /* ... */ 
} 

欲瞭解更多信息和示例,請參閱this#1 Q A.

即使這樣僅輸出目的,可用性__func__ &是相當有限的,因爲它只包括該函數的「非限定名稱」。這對於上面的例子來說只能通過「my_func」。

在C/C++中,這意味着對於重載函數,您將無法通過單獨的值__func__來區分它們。類和/或名稱空間名稱(如果有的話)也不包括在內。

此外編譯器通常提供非標準變化那些包括完整的函數簽名或其他細節(GCC(見__PRETTY_FUNCTION__),Microsoft C/C++(參見__FUNCDNAME____FUNCSIG__))。

+0

...和你所有的例子實際上是**調試**技術。 – SomeWittyUsername

+0

@icepack當然可以。然而,直到現在(我最初寫回答的時候)提到的調試更多的是在實際使用_debugger_而不是執行跟蹤和日誌記錄的情況下。正如我在答案的第二部分所說的那樣,實際上沒有其他可能的使用(由於__func__提供的信息有限)。 –

+0

只需注意:'__func__'不是一個宏:它是該函數本地的'static const'變量。 – Morwenn

2

我注意到,在我的代碼中加入這個宏以及__FILE____LINE__極大地幫助那些正在閱讀我的程序日誌的人。它還使得編寫日誌函數變得更加容易,因爲編譯器會爲我處理這些數據,所以我不需要對這些值進行硬編碼。

請記住,人們可能無法訪問應用程序的源代碼,在某些情況下,只有日誌跟蹤和輸出可供他們使用。如果透明的方式讓他們知道發生了什麼,那將是一件好事。

1

如果它是一個constexpr(它應該是,但至少在當前GCC不是,不幸),它可以被散列和用於實現一個非常簡單和有效的(編譯時,沒有運行時開銷)RTTI系統。

它也可以借給一個更有用的版本std::type_info::hash_code,它既不需要RTTI鏈接,也不允許不同的調用返回不同的值的缺陷。
標準提供的版本(自C++ 11起)沒有明確地給出這樣的保證,這使得它對於除關聯容器中的關鍵字(例如std::map)中的關鍵字之外的任何東西都是無用的。
考慮到保證不同的調用(至少是相同的二進制或者至少具有完全相同的定義的類型),它將更加可用,例如,用於序列化。 (是的,我知道散列函數有衝突,是的,理論上這是一個問題,但是,給定合理的位數(比如64)和合理的密鑰數量(比如幾百) ,它們發生得很少,以至於在實踐中不會出現問題,並且這不是一個無法驗證的問題。)