__PRETTY_FUNCTION __,__ FUNCTION __,__ func__之间有什么区别?

时间:2010-12-08 06:28:27

标签: c++ c compiler-construction standards

__PRETTY_FUNCTION____FUNCTION____func__之间的区别是什么?它们在哪里记录?我如何决定使用哪一个?

5 个答案:

答案 0 :(得分:232)

__func__是一个隐式声明的标识符,当在函数内部使用时,它会扩展为包含函数名的字符数组变量。它被添加到C99的C中。来自C99§6.4.2.2/ 1:

  

标识符__func__由翻译者隐式声明,就像紧跟在每个函数定义的左括号之后的声明一样

static const char __func__[] = "function-name";
     

出现,其中function-name是词法封闭函数的名称。这个名字是函数的简单名称。

请注意,它不是宏,在预处理过程中没有特殊含义。

__func__被添加到C ++ 11中的C ++中,其中它被指定为包含“一个实现定义的字符串”(C ++11§8.4.1[dcl.fct.def.general] / 8),这与C中的规范没有那么有用。(将__func__添加到C ++的原始提案是N1642)。

__FUNCTION__是一些预编译扩展,一些C编译器支持(包括gcc和Visual C ++);一般情况下,你应该使用支持它的__func__,如果使用的是不支持它的编译器,则只使用__FUNCTION__(例如,Visual C ++,它不支持C99但尚未支持支持所有C ++ 0x,不提供__func__)。

__PRETTY_FUNCTION__是一个gcc扩展,与__FUNCTION__大致相同,只是对于C ++函数,它包含函数的“漂亮”名称,包括函数的签名。 Visual C ++有一个类似(但不完全相同)的扩展名__FUNCSIG__

对于非标准宏,您需要查阅编译器的文档。 Visual C ++扩展包含在C ++编译器的"Predefined Macros"的MSDN文档中。 gcc文档扩展名在gcc文档页面"Function Names as Strings."

中进行了描述

答案 1 :(得分:81)

尽管没有完全回答原来的问题,但这可能是大多数人在谷歌搜索想要看到的内容。

GCC:

petanb@debian:~$ cat test.cpp 
#include <iostream>

int main(int argc, char **argv)
{
    std::cout << __func__ << std::endl
              << __FUNCTION__ << std::endl
              << __PRETTY_FUNCTION__ << std::endl;
}
petanb@debian:~$ g++ test.cpp 
petanb@debian:~$ 
petanb@debian:~$ ./a.out 
main
main
int main(int, char**)

答案 2 :(得分:28)

__PRETTY_FUNCTION__处理C ++功能:类,命名空间,模板和重载

#include <iostream>

namespace N {
    class C {
        public:
            template <class T>
            static void f(int i) {
                std::cout << __func__ << std::endl
                          << __FUNCTION__ << std::endl
                          << __PRETTY_FUNCTION__ << std::endl;
            }
            template <class T>
            static void f(double f) {
                std::cout << __PRETTY_FUNCTION__ << std::endl;
            }
    };
}

int main() {
    N::C::f<char>(1);
    N::C::f<void>(1.0);
}

输出GCC 7.2 g++ -std=gnu++98

f
f
static void N::C::f(int) [with T = char]
static void N::C::f(double) [with T = void]

您可能还对具有函数名称的堆栈跟踪感兴趣:print call stack in C or C++

答案 3 :(得分:11)

__func__在第8.4.1节的C ++ 0x标准中有记录。在这种情况下,它是一个预定义的函数局部变量:

static const char __func__[] = "function-name ";

其中“函数名称”是实现特定的。这意味着无论何时声明函数,编译器都会将此变量隐式添加到函数中。 __FUNCTION____PRETTY_FUNCTION__也是如此。尽管它们是大写的,但它们不是宏。虽然__func__是C ++ 0x的补充

g++ -std=c++98 ....

仍将使用__func__编译代码。

这里记录了{p> __PRETTY_FUNCTION____FUNCTION__ http://gcc.gnu.org/onlinedocs/gcc-4.5.1/gcc/Function-Names.html#Function-Names__FUNCTION__只是__func__的另一个名称。 __PRETTY_FUNCTION__与C中的__func__相同,但在C ++中它也包含类型签名。

答案 4 :(得分:5)

对于那些想知道它是如何进入VS的人。

MSVC 2015 Update 1,cl.exe版本19.00.24215.1:

#include <iostream>

template<typename X, typename Y>
struct A
{
  template<typename Z>
  static void f()
  {
    std::cout << "from A::f():" << std::endl
      << __FUNCTION__ << std::endl
      << __func__ << std::endl
      << __FUNCSIG__ << std::endl;
  }
};

void main()
{
  std::cout << "from main():" << std::endl
    << __FUNCTION__ << std::endl
    << __func__ << std::endl
    << __FUNCSIG__ << std::endl << std::endl;

  A<int, float>::f<bool>();
}

输出:

from main():
main
main
int __cdecl main(void)

from A::f():
A<int,float>::f
f
void __cdecl A<int,float>::f<bool>(void)

使用__PRETTY_FUNCTION__按预期触发未声明的标识符错误。