1.指针函数
- 函数返回值为指针类型
- 指针函数不能返回局部变量的地址
char str[32] = {1,2,3,4,5};
//默认存储类型为auto类型,存放在栈区,函数运行结束会被回收,指针指向已经被释放空间的指针,成了野指针
char *pstr = "hello world"; //这是正确的,字符串常量的首地址存放在数据区,值不会随着函数运行结束被回收,程序运行结束才被回收
示例:
#include<stdio.h>
char *InputArray(void)
{
// char str[32] = {"hello world"};
//随着函数运行结束会被回收,指针指向已经被释放空间的指针,成了野指针
char *pstr = "hello world"; //这是正确的
return pstr;
}
int main(void)
{
char *p = NULL;
p = InputArray();
printf("p = %s\\n",p);
return 0;
}
图示:

- 函数返回值作为下一个调用函数参数时可使用指针函数
示例:
#include <stdio.h>
char *MyStrcpy(char *pdst, char *psrc)
{
char *pret = pdst; //保存目标的起始地址(最后要返回)
while (*psrc != '\\0')
{
*pdst = *psrc;
psrc++;
pdst++;
}
*pdst = '\\0';
return pret; //返回目标数组的起始地址(指针函数核心)
}
int main(void)
{
char src[32] = {0};
char dst[32] = {0};
MyStrcpy(dst, MyStrcpy(src, "hello world")); //内层先返回scr的起始地址,外层将scr中的字符串拷贝到dst中,再返回dst的起始地址
printf("dst = %s\\n", dst);
return 0;
}
2.函数指针
- 函数指针是指针,指向一个函数(函数在内存中的入口地址)
- 函数的函数名就是指向该函数的指针(函数名本身就是函数的入口地址)
int Add(int x, int y)
{
return x + y;
}
int(*pfun)(int, int) = NULL; //指针函数的声明格式
- (*pfun)表示pfun是一个指针;
- 括号里的(int,int)表示它指向的函数接收两个int型的参数;
- 函数名前面的int表示它指向的函数返回值的类型是int类型
pfun = Add; //表示把Add的地址赋给指针pfun
3.const指针
等价于Readonly,表示只读
const int *p;
int const *p;
// 两种形式等价,修饰*p;*p只读,
//表示不能用指针修改p指向空间的值,仅可修改指向
//多用于函数传参,仅可修改指向
示例:
int a = 10, b = 20;
const int *p = &a;
p = &b; // 合法:修改指针指向
// *p = 30; 非法:不能修改指向的值
int *const p;
//const修饰p;p只读,表示p的指向不能改变,永远指向同一个地方
//表示指针指向一个固定的地址空间,可以通过指针修改对应空间的值
//必须要初始化,否则为野指针
示例:
int a = 10;
int *const p = &a; // 必须初始化
*p = 20; // 合法:修改指向的值
// p = &b; 非法:不能修改指针指向
const int *const p;
int const *const p;
// 两种形式等价;const 修饰*p, const也修饰 p;
//表示p的指向和p指向空间的值都只读,不能改变
//必须初始化
示例:
int a = 10;
const int *const p = &a; // 必须初始化
// *p = 20; // 非法:不能修改指向的值 // p = &b; // 非法:不能修改指针指向
- 对于const修饰p本身,意味着p存储的地址不能被改变。
- 如果声明时不初始化,p会是一个随机的无效地址,且后续无法修改这个地址,这会导致p成为一个 “不可用的无效指针”。


