代码之家  ›  专栏  ›  技术社区  ›  Matt Joiner

__PRETTY_FUNCTION__、__FUNCTION_、__func__之间有什么区别?

  •  301
  • Matt Joiner  · 技术社区  · 14 年前

    两者之间有什么区别 __PRETTY_FUNCTION__ , __FUNCTION__ , __func__ ,它们记录在哪里?我如何决定使用哪一个?

    5 回复  |  直到 1 年前
        1
  •  353
  •   Community CDub    5 年前

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

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

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

    出现,其中函数名是词法封闭函数的名称。此名称是函数的未修饰名称。

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

    在C++11中,它被添加到C++中,在那里它被指定为包含“一个有实现的字符串”(C++11§8.4.1[dcl.fct.def.general]/8),这不如C中的规范有用 C++是 N1642 ).

    __FUNCTION__ 是一些C编译器支持的预标准扩展(包括gcc和Visual C++);一般来说,你应该使用 __func__ 在支持和仅使用的情况下 __功能__ ).

    __PRETTY_FUNCTION__ 是一个gcc扩展,与 __FUNCSIG__

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

        2
  •  171
  •   ib. Evgeny Shavlyugin    4 年前

    尽管没有完全回答最初的问题,但这可能是大多数谷歌用户想要看到的。

    $ cat test.cpp 
    #include <iostream>
    
    int main(int argc, char **argv)
    {
        std::cout << __func__ << std::endl
                  << __FUNCTION__ << std::endl
                  << __PRETTY_FUNCTION__ << std::endl;
    }
    $ g++ test.cpp 
    $ ./a.out 
    main
    main
    int main(int, char**)
    
        3
  •  85
  •   Ciro Santilli OurBigBook.com    2 年前

    __PRETTY_FUNCTION__

    main.cpp

    #include <iostream>
    
    namespace N {
        class C {
            public:
                template <class T>
                static void f(int i) {
                    (void)i;
                    std::cout << "__func__            " << __func__ << std::endl
                              << "__FUNCTION__        " << __FUNCTION__ << std::endl
                              << "__PRETTY_FUNCTION__ " << __PRETTY_FUNCTION__ << std::endl;
                }
                template <class T>
                static void f(double f) {
                    (void)f;
                    std::cout << "__PRETTY_FUNCTION__ " << __PRETTY_FUNCTION__ << std::endl;
                }
        };
    }
    
    int main() {
        N::C::f<char>(1);
        N::C::f<void>(1.0);
    }
    

    编译并运行:

    g++ -ggdb3 -O0 -std=c++11 -Wall -Wextra -pedantic -o main.out main.cpp
    ./main.out
    

    输出:

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

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

    在Ubuntu 19.04、GCC 8.3.0中测试。

    C++20 std::source_location::function_name

    main.cpp

    #include <iostream>
    #include <string_view>
    #include <source_location>
    
    void log(std::string_view message,
             const std::source_location& location = std::source_location::current()
    ) {
        std::cout << "info:"
                  << location.file_name() << ":"
                  << location.line() << ":"
                  << location.function_name() << " "
                  << message << '\n';
    }
    
    int f(int i) {
        log("Hello world!"); // Line 16
        return i + 1;
    }
    
    int f(double i) {
        log("Hello world!"); // Line 21
        return i + 1.0;
    }
    
    int main() {
        f(1);
        f(1.0);
    }
    

    编译并运行:

    g++ -std=c++20 -Wall -Wextra -pedantic -o main.out main.cpp
    ./main.out
    

    输出:

    info:source_location.cpp:16:int f(int) Hello world!
    info:source_location.cpp:21:int f(double) Hello world!
    

    因此,请注意这是如何返回调用者信息的,因此非常适合在日志中使用,另请参阅: Is there a way to get function name inside a C++ function?

    建议: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1208r5.pdf

    文件说:

    constexpr const char*function_name()const no除外;

    6返回:如果此对象表示函数体中的一个位置, 返回一个实现定义的NTBS,该NTBS应与 函数名称。否则,返回一个空字符串。

    其中NTBS表示“以空结尾的字节串”。

    在GCC 11.3 Ubuntu 22.04上测试。它不在GCC 9.1.0中 g++-9 -std=c++2a .

        4
  •  18
  •   sashang    14 年前

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

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

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

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

    仍将使用以下方式编译代码 __func__ .

    __漂亮功能__ __功能__ 记录在这里 http://gcc.gnu.org/onlinedocs/gcc-4.5.1/gcc/Function-Names.html#Function-Names . __功能__ 只是另一个名字 __func__ . __漂亮功能__ __func__ 在C中,但在C++中,它也包含类型签名。

        5
  •  12
  •   finnan    8 年前

    对于那些想知道VS进展如何的人来说。

    MSVC 2015更新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&ltbool>(void)
    

    使用 __PRETTY_FUNCTION__ 如预期的那样,触发未声明的标识符错误。