g ++ __FUNCTION__替换时间

时间:2010-07-09 14:28:54

标签: c++ string compiler-construction g++ c-preprocessor

有人能说出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__真的被一个字符串替换了吗?或者它是编译代码中的变量?

7 个答案:

答案 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";