2010-07-09 69 views
8

任何人都可以告訴g ++何時用包含函數名稱的字符串替換__FUNCTION__'宏'?這似乎可以代替它直到它有檢查源代碼的語法的正確性,即使用g ++ __FUNCTION__替換時間

g++ -E test.cc 

源看起來預處理後,以下將無法正常工作

#include <whatsneeded> 
#define DBG_WHEREAMI __FUNCTION__ __FILE__ __LINE__ 

int main(int argc, char* argv) 
{ 
    printf(DBG_WHEREAMI "\n"); //* 
} 
因爲

[...] 

int main(int argc, char* argv) 
{ 
    printf(__FUNCTION__ "test.cc" "6" "\n"); //* 
} 

現在編譯器正確拋出,因爲* ed行不正確。

有什麼辦法強制更換字符串到更早的步驟,以便該行是正確的?

是否__FUNCTION__真的被字符串替換了?或者它是編譯代碼中的變量?

回答

15

有沒有辦法強制將替換字符串到前面的步驟,使該行是正確的辦呢?

__FUNCTION__(及其對應的標準化,__func__)是編譯構建體。另一方面,__FILE____LINE__,是預處理器構造。沒有辦法使__FUNCTION__成爲預處理器結構,因爲預處理器不知道C++語言。當源文件被預處理時,預處理器完全不知道它正在查看哪個函數,因爲它甚至沒有函數的概念。

在另一方面,預處理確實知道哪個文件是工作,並且它也知道它正在看文件的哪一行,所以它能夠處理__FILE____LINE__

這就是爲什麼__func__被定義爲等效於靜態局部變量(即編譯器結構);只有編譯器才能提供此功能。

2

__FUNCTION__不是標準配置。使用__func__。作爲documentation說,就好像:

<ret-type> function_name(<args>) 
{ 
    static const char __func__[] = "function-name"; 
    ... 
2

在C/C++,預處理器會變成"my " "name " "is " "Bob"到字符串字面"my name is Bob";由於__FILE____LINE__是預處理器指令,因此"We are on line " __LINE__將向編譯器傳遞「我們在第27行」。

__FUNCTION__通常是__func__的同義詞。 __func__可以被認爲是一個僞函數,它返回調用函數的名稱。這隻能由編譯器完成,而不能由預處理器完成。由於__func__未由預處理器評估,因此不會自動連接。所以,如果你正在使用printf必須由printf("the function name is %s", __func__);

1

這是你想要的嗎?

#include <stdio.h> 

#define DBG_WHEREAMI(X) printf("%s %s(%d): %s\n",__func__,__FILE__,__LINE__,X) 

int main(int argc, char* argv) 
{ 
    DBG_WHEREAMI("Starting"); 
} 

注意:由於您將此標記爲C++,因此您應該使用iostream來確保它是類型安全的。

+0

不幸的是,這不允許像'DBG_WHEREAMI(「錯誤代碼%d」,的errorCode)'。它不能工作,或者(至少不能移植),因爲C++沒有(還)有可變宏。 – 2010-07-10 03:22:20

+0

不完全... 我想知道如果我可以在編譯時生成一個包含__func__的字符串,這是運行時常量。 這似乎是不可能的。 – bbb 2010-07-12 09:50:11

+0

@bbb:它是'static const',它在運行時沒有機會被生成。 – 2013-02-02 05:08:07

0
printf("%s" __FILE__ __LINE__ "\n", __FUNCTION__); 

是的,我知道這不是真的一樣。

0

請注意,如果您創建了一個類,您可以根據需要構建任意數量的類型的消息,這意味着您可以與運算符或printf(3C)中的格式具有類似的效果。事情是這樣的:

// make sure log remains copyable 
class log 
{ 
public: 
    log(const char *function, const char *filename, int line) 
    { 
    f_message << function << ":" << filename << ":" << line << ": "; 
    } 
    ~log() 
    { 
    //printf("%s\n", f_message.str().c_str()); -- printf?! 
    std::cerr << f_message.str() << std::endl; 
    } 

    log& operator() (const char *value) 
    { 
    f_message << value; 
    } 
    log& operator() (int value) 
    { 
    f_message << value; 
    } 
    // repeat with all the types you want to support in the base class 
    // (should be all the basic types at least) 
private: 
    sstream f_message; 
}; 

// start the magic here 
log log_error(const char *func, const char *file, int line) 
{ 
    log l(func, file, line); 
    return l; 
} 

// NOTE: No ';' at the end here! 
#define LOG_DEBUG log_error(__func__, __FILE__, __LINE__) 

// usage sample: 
LOG_DEBUG("found ")(count)(" items"); 

需要注意的是,你可以聲明< <運營商,而不是()。在這種情況下,結果使用情況如下:

LOG_DEBUG << "found " << count << " items"; 

取決於您更喜歡使用哪種方式。我喜歡(),因爲它會自動保護你的表情。也就是說,如果你想輸出「算< < 3」,那麼你就必須寫:

LOG_DEBUG << "found " << (count << 3) << " items";