1. 什么是__FUNCTION__
__FUNCTION__是 C/C++ 编译器提供的预定义宏(也叫内置宏),它会在编译阶段被自动替换为当前函数的名称(字符串形式)。简单来说,它就是一个 “函数名标签”,能让程序在运行时知道自己正处在哪个函数里。
需要注意:
- 它是编译器扩展(非标准 C/C++,但几乎所有主流编译器如 GCC、Clang、MSVC 都支持);
- 与
__func__(C99 标准)功能几乎一致,__FUNCTION__是更早的非标准写法,兼容性更广。
2.__FUNCTION__的核心用途
最核心的价值是调试和日志输出,其次是简化代码维护,具体看这几个场景:
场景 1:调试 / 日志(最常用)
当程序报错或输出日志时,用__FUNCTION__可以精准定位到问题所在的函数,不用手动写函数名,既高效又避免写错。
示例代码:
#include <stdio.h> void calculate_sum(int a, int b) { // 打印当前函数名 + 关键信息,方便调试 printf("[%s] 开始计算 %d + %d\n", __FUNCTION__, a, b); int sum = a + b; printf("[%s] 计算结果:%d\n", __FUNCTION__, sum); } void print_error(const char* msg) { // 错误日志中带上函数名,快速定位问题 fprintf(stderr, "[ERROR][%s]:%s\n", __FUNCTION__, msg); } int main() { calculate_sum(3, 5); print_error("参数不能为空"); return 0; }输出结果:
[calculate_sum] 开始计算 3 + 5 [calculate_sum] 计算结果:8 [ERROR][print_error]:参数不能为空场景 2:断言(Assert)增强
结合assert使用,断言失败时能直接显示出错的函数名,定位更精准:
#include <assert.h> #include <stdio.h> void divide(int a, int b) { // 断言失败时,会打印函数名 + 断言条件 assert(b != 0 && __FUNCTION__); printf("%d / %d = %d\n", a, b, a/b); } int main() { divide(10, 0); // 触发断言 return 0; }输出(GCC):
a.out: test.c:7: divide: Assertion `b != 0 && __FUNCTION__' failed. Aborted (core dumped)能直接看到是divide函数中b=0导致断言失败。
场景 3:简化代码维护
如果手动写函数名到日志里,后续修改函数名时需要同步改日志中的字符串,容易遗漏;用__FUNCTION__则完全不用管,编译器会自动更新。
3. 注意事项
__FUNCTION__只在函数内部有效,全局作用域中使用会报错 / 无意义;- C++ 中还可以用
__PRETTY_FUNCTION__(GCC/Clang)或__FUNCSIG__(MSVC),能显示更详细的函数签名(如参数类型、返回值、类名); - 它是编译期替换,不是运行时获取,性能无损耗。
总结
__FUNCTION__是编译器内置宏,编译时替换为当前函数名(字符串);- 核心用途是调试 / 日志 / 断言,能精准定位代码执行位置,简化维护;
- 兼容性好,几乎所有 C/C++ 编译器都支持,是调试排错的实用工具。