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

Mat*_*ner 205 c c++ compiler-construction standards

什么之间的区别__PRETTY_FUNCTION__,__FUNCTION__,__func__,和他们在哪里记录?我如何决定使用哪一个?

Jam*_*lis 246

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

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

static const char __func__[] = "function-name";
Run Code Online (Sandbox Code Playgroud)

出现了,其中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++编译器的"预定义宏"的MSDN文档中.gcc文档扩展在gcc文档页面"函数名称为字符串"中进行了描述.

  • 请注意,尽管gcc和VC都提供了“ __FUNCTION__”,但它们的功能略有不同。gcc等于`__func__`。VC给出了该名称的未经修饰但仍经过修饰的版本。对于名为“ foo”的方法,gcc将给您“ foo”,VC将给“ my_namespace :: my_class :: foo”。 (2认同)
  • @FrancisCugler 我也对此感到惊讶!查看我的问题/sf/ask/3420052121/ (2认同)

Pet*_*etr 97

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

对于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**)
Run Code Online (Sandbox Code Playgroud)

  • 来自clang 3.5的相同输出 (13认同)
  • @Petr严格来说`__func__`是一个预定义的标识符,而不是宏。 (7认同)
  • 我知道这不是一个正确的答案,但它可能是几乎所有google想要看到的人:)(如果他们懒得试试自己) (6认同)
  • 公平的电话,这很好看. (5认同)

Cir*_*四事件 36

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

#include <iostream>

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

int main() {
    N::C::f<char>(1);
    N::C::f<void>(1.0);
}
Run Code Online (Sandbox Code Playgroud)

输出GCC 7.2 source_location::function_name:

g++ -ggdb3 -O0 -std=c++11 -Wall -Wextra -pedantic -o main.out main.cpp
./main.out
Run Code Online (Sandbox Code Playgroud)

您可能还对具有函数名称的堆栈跟踪感兴趣:使用C或C++打印调用堆栈


sas*_*ang 12

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

static const char __func__[] = "function-name ";
Run Code Online (Sandbox Code Playgroud)

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

g++ -std=c++98 ....
Run Code Online (Sandbox Code Playgroud)

仍将使用编译代码__func__.

__PRETTY_FUNCTION____FUNCTION__在此处记录http://gcc.gnu.org/onlinedocs/gcc-4.5.1/gcc/Function-Names.html#Function-Names.__FUNCTION__只是另一个名字__func__.__PRETTY_FUNCTION____func__C中的相同,但在C++中它也包含类型签名.

  • @JamesMcNellis 现在,清除评论,消除噪音 (3认同)

fin*_*nan 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>();
}
Run Code Online (Sandbox Code Playgroud)

输出:

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__正如预期的那样使用触发器未声明的标识符错误.

  • `void main()` 在技术上是不正确的。“main”,无论如何根据参数定义,都必须返回“int”。 (2认同)