谁能告诉 g++ 何时将
__FUNCTION__
'宏' 替换为包含函数名称的字符串?看来只有检查源代码的语法正确性后才能替换它,即以下内容将不起作用
#include <whatsneeded>
#define DBG_WHEREAMI __FUNCTION__ __FILE__ __LINE__
int main(int argc, char* argv)
{
printf(DBG_WHEREAMI "\n"); //*
}
自从使用预处理后
g++ -E test.cc
来源看起来像
[...]
int main(int argc, char* argv)
{
printf(__FUNCTION__ "test.cc" "6" "\n"); //*
}
现在编译器正确地抛出了错误,因为 *ed 行不正确。
有什么方法可以强制用字符串替换到较早的步骤,以便该行正确吗?
__FUNCTION__
真的被字符串取代了吗?或者它是编译代码中的变量?
有什么方法可以强制用字符串替换到较早的步骤,以便该行正确吗?
不。
__FUNCTION__
(及其标准化对应物,__func__
)是编译器构造。另一方面,__FILE__
和__LINE__
是预处理器构造。无法使 __FUNCTION__
成为预处理器构造,因为预处理器不了解 C++ 语言。当源文件被预处理时,预处理器完全不知道它正在查看哪个函数,因为它甚至没有函数的概念。
另一方面,预处理器确实知道它正在处理哪个文件,并且它也知道它正在查看文件的哪一行,因此它能够处理
__FILE__
和__LINE__
。
这就是为什么
__func__
被定义为等同于静态局部变量(即 compiler 构造);只有编译器可以提供此功能。
您像预处理器宏一样使用
__FUNCTION__
,但它是一个变量(请阅读 http://gcc.gnu.org/onlinedocs/gcc/Function-Names.html)。
尝试
printf("%s", __FUNCTION__)
只是为了测试,它会打印函数名称。
__FUNCTION__
不是标准的。使用__func__
。正如文档所说,就好像:
<ret-type> function_name( <args> )
{
static const char __func__[] = "function-name";
...
在 C/C++ 中,预处理器会将
"my " "name " "is " "Bob"
转换为字符串文字 "my name is Bob"
;由于 __FILE__
和 __LINE__
是预处理器指令,因此 "We are on line " __LINE__
会将“We are on line 27”传递给编译器。
__FUNCTION__
通常是 __func__
的同义词。 __func__
可以被认为是一个伪函数,它返回调用它的函数的名称。这只能由编译器完成,而不能由预处理器完成。由于预处理器不评估 __func__
,因此您不会获得自动串联。因此,如果您使用 printf
,则必须由 printf("the function name is %s", __func__);
完成
这是你想要的吗?
#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++,您可能应该使用 iostreams 来确保它的类型安全。
printf("%s" __FILE__ __LINE__ "\n", __FUNCTION__);
是的,我知道这并不完全一样。
请注意,如果您创建一个类,您可以根据需要从任意数量的类型构建消息,这意味着您具有与 << operator or the format in a printf(3C). Something like this:
类似的效果// 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");
请注意,您可以声明 << operators instead of the (). In that case the resulting usage would be something like this:
LOG_DEBUG << "found " << count << " items";
取决于您喜欢使用哪种。我有点喜欢 () 因为它会自动保护你的表达式。即如果你想输出“count << 3" then you'd have to write:
LOG_DEBUG << "found " << (count << 3) << " items";