有人能说出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__
真的被一个字符串替换了吗?或者它是编译代码中的变量?
答案 0 :(得分:15)
有没有办法强制用字符串替换前一步,以便该行正确?
没有。 __FUNCTION__
(及其标准化版本__func__
)是编译器构造。另一方面,__FILE__
和__LINE__
是预处理器构造。没有办法使__FUNCTION__
成为预处理器构造,因为预处理器不了解C ++语言。在对源文件进行预处理时,预处理器完全不知道它正在查看哪个 function ,因为它甚至没有函数的概念。
另一方面,预处理器 知道它正在处理哪个文件,并且它还知道它正在查看的文件的哪一行,因此它能够处理{{1} }和__FILE__
。
这就是为什么__LINE__
被定义为等同于静态局部变量(即编译器构造)的原因;只有编译器才能提供此功能。
答案 1 :(得分:3)
您正在使用__FUNCTION__
之类的预处理器宏,但它是一个变量(请阅读http://gcc.gnu.org/onlinedocs/gcc/Function-Names.html)。
尝试printf("%s", __FUNCTION__)
仅用于测试,它将打印函数名称。
答案 2 :(得分:2)
__FUNCTION__
不标准。使用__func__
。正如documentation所说的那样,就好像:
<ret-type> function_name( <args> )
{
static const char __func__[] = "function-name";
...
答案 3 :(得分: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__);
答案 4 :(得分: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来确保其类型安全。
答案 5 :(得分:0)
printf("%s" __FILE__ __LINE__ "\n", __FUNCTION__);
是的,我知道那不一样。
答案 6 :(得分:0)
请注意,如果您创建了一个类,则可以根据需要从任意数量的类型构建消息,这意味着您对&lt;&lt;运算符或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");
请注意,您可以声明&lt;&lt;运算符而不是()。在这种情况下,产生的用法将是这样的:
LOG_DEBUG << "found " << count << " items";
取决于您喜欢使用哪种。我有点像()因为它会自动保护你的表达式。即如果你想输出“count&lt;&lt;&lt; 3”那么你必须写:
LOG_DEBUG << "found " << (count << 3) << " items";