__FUNCTION__ 是 GCC、Clang 和 MSVC 支持的预定义标识符,非标准但广泛兼容,展开为当前函数未修饰名的 const char[] 字符串;推荐新项目使用标准 __func__。

直接用 __FUNCTION__ 就能拿到当前函数名字符串,但它是编译器扩展,不是标准 C++,行为和内容取决于编译器。
__FUNCTION__ 是什么、从哪来
__FUNCTION__ 是 GCC、Clang 和 MSVC 都支持的预定义标识符(注意:它不是宏,没有括号),在函数作用域内展开为一个以 null 结尾的 const char[] 字符串字面量,值为该函数的“未修饰名”(unmangled name)。
它和 __func__(C99 / C++11 标准)功能基本一致,但 __FUNCTION__ 更早被广泛支持,且部分编译器对模板/重载函数的处理略有不同。
-
__func__是标准写法,推荐新项目优先用它 -
__FUNCTION__在老代码或需兼容旧 GCC(如 4.4 以下)时仍常见 - 两者都不能在全局作用域或 lambda 内部直接使用(lambda 没有函数名)
实际用法与常见错误
最常见错误是把它当宏调用,比如写成 __FUNCTION__() 或 __FUNCTION__ + "suffix" —— 它是常量数组,不是函数,也不能直接拼接字符串。
立即学习“C++免费学习笔记(深入)”;
正确用法示例:
void example_func(int x) {
std::cout << "In function: " << __FUNCTION__ << ", x = " << x << "\n";
// 输出类似:In function: example_func, x = 42
}
- 不能取地址再解引用:
std::string s(*__FUNCTION__);❌(__FUNCTION__是数组,*得到首字符) - 正确转
std::string:std::string(__FUNCTION__)✅ - 在模板中会显示实例化后的函数名,如
foo,但 MSVC 可能只显示foo - 类成员函数会包含作用域,如
MyClass::doWork(GCC/Clang),MSVC 可能省略class前缀
和 __PRETTY_FUNCTION__ 的关键区别
__PRETTY_FUNCTION__(GCC/Clang)或 __FUNCSIG__(MSVC)提供更完整的签名信息,包括返回类型、参数类型、模板实参等。
templatevoid process(T t) { std::cout << "__FUNCTION__: " << __FUNCTION__ << "\n"; std::cout << "__PRETTY_FUNCTION__: " << __PRETTY_FUNCTION__ << "\n"; } // 调用 process(42) 输出: // __FUNCTION__: process // __PRETTY_FUNCTION__: void process(T) [with T = int]
-
__FUNCTION__短小、可预测、跨平台兼容性好,适合日志打点、断言上下文 -
__PRETTY_FUNCTION__信息全但长度不可控,可能触发栈溢出(尤其深度模板嵌套),且 MSVC 不支持 - 若需稳定可读的函数标识(比如注册回调),别依赖任一内置标识符,应显式传入字符串字面量
不推荐用于生产级函数名反射
靠 __FUNCTION__ 实现“根据函数名调用函数”是危险的:它不提供符号地址、无法查重载、不支持链接时解析。真要动态调用,请用函数指针表、std::map<:string std::function>> 显式注册,或借助 ABI 工具(如 dlsym + extern "C" 符号)。
它的真正价值在于调试辅助——快速定位执行位置,而不是构建运行时反射系统。











