引言
指针是 C 语言的灵魂,也是初学者公认的难点。在上一篇文章中,我们梳理了指针的基本概念,今天将聚焦指针的高频进阶用法 —— 包括容易混淆的函数指针与指针函数、需要精准区分的const 指针家族(指向常量的指针、常量指针、指向常量的常量指针),结合实战案例拆解核心逻辑,帮你彻底吃透这些抽象知识点!
1、指针函数和函数指针
很多初学者会把「函数指针」和「指针函数」混为一谈,其实二者是完全不同的概念:指针函数是 “返回指针的函数”,函数指针是 “指向函数的指针”。
1.1 指针函数
返回类型* 函数名(参数列表);
函数返回值为指针类型的函数,称为指针函数
指针函数不能返回局部变量的地址
函数返回值 作为下一个调用函数 参数时可以使用指针函数
示例:
#include <stdio.h>
int g = 100;
int* getAddr() {
return &g; // 返回 int* 类型
}
int main() {
int *p = getAddr();
printf("%d\\n", *p); // 输出100
return 0;
}
1.2 函数指针
函数指针是 指向函数的指针变量, 本质就是保存一个函数的入口地址
返回类型 (*指针名)(参数类型列表);
-
和数组名代表数组首地址类似,函数名代表函数的入口地址。
-
函数的函数名就是指向该函数的指针
-
所以可以用一个指针来存储它,然后通过指针调用函数。
示例:
#include <stdio.h>
int add(int a, int b) {
return a + b;
}
int main() {
// 如果需初始化,直接int (*fp)(int, int) = NULL;
// 定义一个函数指针,指向返回int,参数(int,int)的函数
int (*fp)(int, int);
fp = add; // 或者 fp = &add;
printf("%d\\n", fp(2, 3)); // 通过函数指针调用
printf("%d\\n", (*fp)(5, 7)); // 等价写法
return 0;
}
回调函数 (Callback):将函数作为参数传递。
// 回调函数示例
void process_array(int *arr, int size, int (*process)(int)) {
for (int i = 0; i < size; i++) {
arr[i] = process(arr[i]);
}
}
int double_value(int x) { return x * 2; }
int square_value(int x) { return x * x; }
int main() {
int numbers[] = {1, 2, 3, 4, 5};
process_array(numbers, 5, double_value);
// numbers 变为 [2, 4, 6, 8, 10]
process_array(numbers, 5, square_value);
// numbers 变为 [4, 16, 36, 64, 100]
return 0;
}
2、const指针
const 等价于read only,表示只读
const与指针结合的写法是面试高频考点,核心要分清const修饰的是指针本身,还是指针指向的内容。
核心判断规则(万能公式)
const 修饰其左侧的内容;若左侧无内容,则修饰右侧的内容。
2.1 指向常量的指针
int const *p;
const int *p;
指针本身可以改变(指向别的地址),但不能通过这个指针来修改它所指对象的值。
示例:
int value = 10;
const int *ptr = &value; // ptr 是一个指向 const int 的指针
// 或者 int const *ptr = &value; (两种写法完全等价)
// *ptr = 20; // 错误!不能通过 ptr 修改 value 的值
value = 20; // 正确!value 本身不是常量,可以直接修改
int another_value = 30;
ptr = &another_value; // 正确!ptr 本身可以指向别的地址
用途:多用于函数传参,指针指向的空间中的数据不能修改
用于函数参数,表示“我不会通过这个指针修改你传进来的数据”,保护原始数据。
2.2 常量指针
int *const P;
(1)指针本身是常量(指向的地址不能变),但可以通过它修改所指对象的值(只要对象本身不是常量)。
(2)指针必须初始化
示例:
int value = 10;
int *const ptr = &value; // ptr 是一个常量指针,指向 int
*ptr = 20; // 正确!可以通过 ptr 修改 value 的值
int another_value = 30;
// ptr = &another_value; // 错误!ptr 本身是常量,不能再指向别处
**用途**:确保一个指针在整个生命周期内始终指向同一个对象。
2.3 指向常量的指针
int const *const p;
const int *const p;
(1)两者都是常量:指针不能指向别处,也不能通过它修改所指对象的值。
(2)指针必须初始化
int value = 10;
const int *const ptr = &value; // ptr 是一个常量指针,指向一个常量 int
// *ptr = 20; // 错误!不能通过 ptr 修改值
// ptr = &another_value; // 错误!ptr 本身不能改变指向c
value = 20; // 正确!只要 value 本身不是 const
3、易混概念澄清
- “指针常量” vs “常量指针”:二者是同一概念(即int *const p),只是叫法不同;而 “指向常量的指针”(const int *p)是独立概念,需与前两者区分。
- 函数指针 vs 指针函数:二者无任何等价关系 —— 指针函数是 “返回指针的函数”(本质是函数),函数指针是 “指向函数的指针”(本质是指针),切勿混淆。
本文拆解了指针的两大核心进阶用法:
我们今天就先介绍到这里了,这些内容第一次学习还是不太好理解的,就比如函数指针就有一点抽象,同时它的功能也很强大,适合去做一些整体的封装应用,比如就像计算机计算加减乘除这种的 ,所以希望各位友友们好好理解并掌握这些内容,下次将会继续为大家讲解指针的内容,比如:数组指针,指针数组等,敬请期待吧!
各位友友如果觉得本文对你理解指针有帮助,欢迎点赞 + 收藏 + 关注(一键三连)!如果发现内容有疏漏,或对某个知识点有不同看法,欢迎在评论区留言讨论,一起交流进步~那我们就下次再见啦!




