2010-07-09 31 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";