g++ __FUNCTION__ 替换时间

问题描述 投票:0回答:7

谁能告诉 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__
真的被字符串取代了吗?或者它是编译代码中的变量?

c++ string g++ c-preprocessor
7个回答
15
投票

有什么方法可以强制用字符串替换到较早的步骤,以便该行正确吗?

不。

__FUNCTION__
(及其标准化对应物,
__func__
)是编译器构造。另一方面,
__FILE__
__LINE__
预处理器构造。无法使
__FUNCTION__
成为预处理器构造,因为预处理器不了解 C++ 语言。当源文件被预处理时,预处理器完全不知道它正在查看哪个函数,因为它甚至没有函数的概念。

另一方面,预处理器确实知道它正在处理哪个文件,并且它也知道它正在查看文件的哪一行,因此它能够处理

__FILE__
__LINE__

这就是为什么

__func__
被定义为等同于静态局部变量(即 compiler 构造);只有编译器可以提供此功能。


3
投票

您像预处理器宏一样使用

__FUNCTION__
,但它是一个变量(请阅读 http://gcc.gnu.org/onlinedocs/gcc/Function-Names.html)。

尝试

printf("%s", __FUNCTION__)
只是为了测试,它会打印函数名称。


2
投票

__FUNCTION__
不是标准的。使用
__func__
。正如文档所说,就好像:

<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__
会将“We are on 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++,您可能应该使用 iostreams 来确保它的类型安全。


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

是的,我知道这并不完全一样。


0
投票

请注意,如果您创建一个类,您可以根据需要从任意数量的类型构建消息,这意味着您具有与 << 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";
© www.soinside.com 2019 - 2024. All rights reserved.