函数指针声明必须用(*ptr)括号明确指针属性,否则被误解析为函数;指针函数返回指针值,需防悬空指针;二者语法仅差括号但语义迥异,须用typedef或using简化并注重空值检查与内存管理。

函数指针:声明时括号必须包住 (*ptr)
函数指针本质是变量,存的是函数地址。声明时(*ptr)的括号不能省——这是编译器识别“这是个指针,不是函数”的唯一依据。漏掉括号,比如写成int *ptr(int),编译器会按指针函数解析,直接报错或行为错乱。
常见错误现象:error: 'xxx' declared as function returning a function,基本就是括号位置错了。
-
int (*cmp)(const void*, const void*)是qsort要求的函数指针类型,(*cmp)明确表示 cmp 是指针 - 赋值时可用函数名(如
cmp = my_compare),也可加取址符&my_compare,两者等价 - 调用方式有两种:
cmp(a, b)或(*cmp)(a, b),前者更常用也更直观
指针函数:int* func() 中的 * 属于返回类型
指针函数本质是函数,只是返回值恰好是个指针。声明里int*连写,*紧贴类型,不跟函数名绑定。它和普通函数唯一区别就是返回类型带*。
容易踩的坑是返回局部变量地址:char* get_msg() { char buf[32] = "hi"; return buf; }——这会导致悬空指针,调用后内容不可靠。
- 安全做法:返回
static变量、堆内存(如new或malloc)、或全局/类静态成员 - 典型场景:封装资源分配,如
int* create_array(size_t n);或返回字符串常量地址,如const char* error_msg(int code) - C++ 中若返回堆内存,调用方必须负责
delete[]或free,否则内存泄漏
混淆点:int* f(); 和 int (*f)(); 差一个括号,语义天壤之别
这两个声明看着像,但一个是函数,一个是指针,编译器完全当不同类型处理。C++ 不允许隐式转换,传参或赋值时类型不匹配会直接编译失败。
-
int* f();→ 指针函数:调用f()得到一个int*,再解引用才拿到值 -
int (*f)();→ 函数指针:f本身是变量,f()直接调用它指向的函数,返回int - 调试时看变量类型:在 IDE 或
gdb里打印typeof(f),能立刻分清是int* (*)()还是int* ()
typedef 和 using 可大幅降低阅读负担
裸写 int (*func_ptr)(double, bool) 容易眼花,而且复制粘贴时括号极易出错。用类型别名封装后,语义清晰、复用方便。
- C 风格:
typedef int (*CompareFunc)(const void*, const void*); CompareFunc cmp = my_cmp; - C++11+ 推荐:
using CompareFunc = int (*)(const void*, const void*); - 对指针函数也可简化:
using ArrayPtr = int*; ArrayPtr create_arr(int n);,虽不如函数指针刚需,但统一风格更稳妥
真正容易被忽略的,不是语法本身,而是函数指针赋值后是否检查空值、指针函数返回的内存谁来释放——这些不是编译能拦住的,得靠约定和文档。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











