回调函数
函数指针最常用的地方在于将一个函数作为参数传递给另一个函数的时候要用函数指针,将一个函数作为参数传递给另外一个函数,将这个函数称为回调函数。
回调就是一种利用函数指针进行函数调用的过程。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,就说这是回调函数。
例子:
#include<stdio.h>
int add(int a, int b);
int sub(int a, int b);
int mul(int a, int b);
int div(int a, int b);
int mod(int a, int b);
int calculate(int (*p)(int,int),int a, int b);
int main()
{
int a = 20, b = 10, ret;
int (*p)(int,int);
p = add;
printf("%d\n", p(a,b));
p = sub;
printf("%d\n", p(a,b));
ret = calculate(add,a,b);
printf("%d\n",ret);
ret = calculate(sub,a,b);
printf("%d\n",ret);
ret = calculate(mul,a,b);
printf("%d\n",ret);
ret = calculate(div,a,b);
printf("%d\n",ret);
ret = calculate(mod,a,b);
printf("%d\n",ret);
return 0;
}
int add(int a, int b)
{
return a+b;
}
int sub(int a, int b)
{
return a-b;
}
int mul(int a, int b)
{
return a*b;
}
int div(int a, int b)
{
return a/b;
}
int mod(int a, int b)
{
return a%b;
}
int calculate(int (*p)(int,int),int a, int b)
{
return p(a,b);
}
函数指针数组
定义: 本质是一个数组,数组里面的每一个元素都是一个函数指针
格式: 返回值类型 (* 函数指针变量名[函数指针的个数]) (形参列表)
int(* p[10])(int,int)
例子:
#include<stdio.h>
int add(int a, int b)
{
return a+b;
}
int sub(int a, int b)
{
return a-b;
}
int mul(int a, int b)
{
return a*b;
}
int div(int a, int b)
{
return a/b;
}
int mod(int a, int b)
{
return a%b;
}
int main()
{
int a = 20;
int b = 10;
int i;
//定义一个指针数组
//数组有5个元素,数组中每个元素都是一个函数指针,指针指向一个函数的首地址
//函数的返回值是int型,有两个int型入参
int (*p[5])(int,int) = {add, sub, mul, div, mod};
for(i = 0; i < 5; i++)
{
printf("%d\n",p[i](a,b));
}
return 0;
}
只读指针变量
定义: 当我们将const关键字加到* 和 指针变量名之间的时候,这时指针变量内存储的地址值不可修改。
格式: 将const关键字加到* 和 指针变量名之间
例子:
//只读指针变量
#include<stdio.h>
int main()
{
int a = 20;
int b = 10;
int * const p = &a;
printf("%p\n",p);
printf("%d\n",*p);
// p = &b; //用const修饰的指针变量的地址不能被修改,如果修改了程序会报错
// printf("%p\n",p);
// printf("%d\n",*p);
return 0;
}
只读变量指针
定义: 当我们将const关键字加到,变量声明类型和 * 之间的时候,这时指针变量内存储的地址值不可修改。
格式: 将const关键字加到变量声明类型和 * 之间
例子:
//只读变量指针
#include<stdio.h>
int main()
{
int a = 20;
int b = 10;
int const *p = &a;
printf("%p\n",p);
printf("%d\n",*p);
// *p = 100; //用const修饰的指针变量指向的值的不能被修改,如果修改了程序会报错
// printf("%p\n",p);
// printf("%d\n",*p);
return 0;
}
只读变量
定义: 当我们将const关键字加到,变量声明类型和 * 之间以及加到* 和 指针变量名之间的时候,这时指针变量内存储的地址值不可修改,指针变量指向的值也不能修改。
格式: 将const关键字加到变量声明类型和 * 之间以及将const关键字加到* 和 指针变量名之间
例子:
//只读变量
#include<stdio.h>
int main()
{
int a = 20;
int b = 10;
int const * const p = &a;
printf("%p\n",p);
printf("%d\n",*p);
// *p = 100; //前面const修饰的,值不能被改,如果修改了程序会报错
// printf("%p\n",p);
// printf("%d\n",*p);
// p = &b; //后面const修饰的,地址不能被改,如果修改了程序会报错
// printf("%p\n",p);
// printf("%d\n",*p);
return 0;
}
特殊指针
1.硬编码赋值给指针
指针变量是指向变量的地址
int *p = 100; //没有意义,无法确定100这个地址是否被占用,编译器会警告
2.空指针
int *p2 = NULL; //一般用于初始化,不确定什么时候使用,先指向空
3.野指针
野指针分为两种情况:
- 指针在定义时未初始化,它会随机指向一个区域,因为任意指针变量(除了static修饰的指针)
它的默认值都是随机的;
- 在使用malloc()函数开辟完空间之后,指针指向的内存空间在用free()释放之后,如果没有对释放后的指针赋值为NULL,那么也会变为野指针。
4.万能指针
void * (也称为空类型指针)
void * 指针可以指向任意变量的内存空间
例子:
#include<stdio.h>
int main()
{
int a = 10;
char ch = 'a';
float b = 1.2;
void *pp;
pp = &a;
printf("%p\n",pp);
//直接打印pp的值会报错,因为pp是一个void型的指针
// printf("%d\n",*pp);
//需要将void型的指针转换成int型指针再打印值
printf("%d\n",*((int *)pp));
//通过万能指针修改变量内容值,需要指定变量对应的指针类型
*((int*)pp) = 100;
printf("%d\n",*((int *)pp));
*((char *)pp) = 'c';
printf("%c\n",*((char *)pp));
pp = &ch;
printf("%p\n",pp);
pp = &b;
printf("%p\n",pp);
return 0;
}