__func__ 是 iso c++11 标准预定义标识符,于函数体内自动声明为 static const char[] 类型,值为当前函数名(不含命名空间或类作用域),无需头文件且跨编译器兼容;不可在函数外使用或通过宏滥用。

用 __func__ 是最直接、标准的方式
ISO C++11 起,__func__ 就是合法的预定义标识符,它在每个函数作用域内自动声明为 static const char[] 类型,值为当前函数名(不含命名空间或类作用域)。不需要头文件,不依赖编译器扩展。
常见误用是把它当宏用,比如 #define FUNC __func__ 后在函数外调用——这会崩,因为 __func__ 只在函数体内有效。
- ✅ 正确:
void foo() { std::cout - ❌ 错误:
std::cout
- ⚠️ 注意:在模板函数里,
__func__展开的是实例化后的函数名(如foo<int></int>),不是模板声明名
__FUNCTION__ 和 __PRETTY_FUNCTION__ 的区别在哪
__FUNCTION__ 是 GCC/Clang 扩展,行为和 __func__ 基本一致;而 __PRETTY_FUNCTION__ 是 GCC/Clang 特有,会包含完整签名(返回类型、参数、const 限定符、模板实参等)。
跨平台项目里优先用 __func__;调试时想快速看类型信息,__PRETTY_FUNCTION__ 更直观,但体积大、不可移植。
-
__func__→"bar" -
__FUNCTION__→ 同上(GCC/Clang 下) -
__PRETTY_FUNCTION__→"void bar(const std::string&)"(GCC)或"auto bar(const std::string &) -> void"(Clang) - MSVC 不支持后两者,但支持
__FUNCSIG__(类似__PRETTY_FUNCTION__)
想带命名空间或类名?得手动拼接
__func__ 永远只给裸函数名。如果在 ns::A::method() 里,它只返回 "method",不会补全前缀。没有标准方式自动获取完整限定名。
可行做法是宏辅助(但有局限):
#define FULL_FUNC_NAME ::boost::core::demangle(typeid(*this).name()).c_str(), __func__
这只对非静态成员函数有效,且依赖 RTTI 和 typeid,开启 -fno-rtti 就失效。更稳妥的是显式写字符串,比如日志宏里传 "ns::A::method" —— 看似冗余,实则稳定、无开销、无 ABI 风险。
性能和调试符号的关系别搞混
__func__ 是编译期常量,不依赖调试信息(-g),也不产生运行时开销。即使 strip 掉二进制,它照样工作。
容易混淆的是 backtrace_symbols() 或 addr2line 这类工具——它们靠 DWARF 或符号表,关掉 -g 就没函数名。但 __func__ 完全不走这条路。
- 发布版代码想打函数名日志?放心用
__func__ - 想从地址反查函数名?那是调试符号的事,跟
__func__无关 - 宏里用
__func__没问题,但别试图在宏定义里跨函数引用它
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











