1.通过函数指针变量调用 ?? ?定义一个函数指针,这个指针指向的函数返回值是int型,入参是两个int型 ?? ?相同类型的指针可以相互赋值?
int a = 20;
int b = 10;
int (*p)(int,int);//定义一个函数指针,这个指针指向的函数返回值是int型,入参是两个int型
int (*q)(int ,int);//相同类型的指针可以相互赋值
p = add;//函数名表示函数的首地址
printf("%p\n",p);
printf("%d\n",p(a,b));
p = sub;
printf("%p\n",p);
printf("%d\n",p(a,b));
函数指针最常用的地方在于将一个函数作为参数传递给另一个函数的时候要用函数指针 ?? ?将一个函数作为参数传递给另外一个函数,将这个函数称为回调函数。
#include<stdio.h>
//两数相加
int add(int a,int b)
{
return a+b;
}
//两数相减
int sub(int a,int b)
{
return a-b;
}
//两数相乘
int cheng(int a,int b)
{
return a*b;
}
//两数相除
int ave(int a,int b)
{
return a/b;
}
//两数取余
int yu(int a,int b)
{
return a%b;
}
int caculator(int (*p)(int,int),int a,int b)//将函数指针作为一个函数的入参,这是回调函数
{
return p(a,b);
}
int main()
{
int a = 20;
int b = 10;
int (*p)(int,int);//定义一个函数指针,这个指针指向的函数返回值是int型,入参是两个int型
int (*q)(int ,int);//相同类型的指针可以相互赋值
p = add;//函数名表示函数的首地址
//两数相加返回的函数
int ret = caculator(add,a,b);
printf("%d\n",ret);
//两数相减返回的函数
ret = caculator(sub,a,b);
printf("%d\n",ret);
//两数相乘返回的函数
ret = caculator(cheng,a,b);
printf("%d\n",ret);
//两数相除返回的函数
ret = caculator(ave,a,b);
printf("%d\n",ret);
//两数取余返回的函数
ret = caculator(yu,a,b);
printf("%d\n",ret);
return 0;
}
例:用函数指针实现三个数相加
int ret = add(a,b);
int sum = caculator(add,ret,c);
printf("%d\n",sum);
2.指针函数数组 ?? ?本质是一个数组,数组里面的每一个元素都是函数一个函数指针 ?? ?返回值类型 ? (*函数指针变量名[函数指针的个数]) (形参列表)? ?? ?int (*p[10])(int,int)? ?? ?定义了一个函数指针数组,数组中有5个元素p[0]~p[4],每个元素都是函数指针变量,该函数指针变量指向的函数必须有整形的返回值和两个整形参数。(有两种做法均在下方)
#include<stdio.h>
//函数指针数组
//本质是一个数组,数组里面的每一个元素都是一个函数指针
//返回值类型 (*函数指针变量名[函数指针的个数]) (形参列表)
//int (*p[10])(int,int)
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 c = 30;
//定义一个函数指针数组
//数组有5个元素,数组中的每一个元素都是函数指针,指针指向一个函数的首地址
//函数的返回值是int型,有两个int型入参
//第一种方法
// int (*p[5])(int,int) = {add,sub,mul,div,mod};
//等价于上面函数初始化
//第二种方法定义指针数组并给各个数组赋值数组赋值
int (*p[5])(int,int);
p[0] = add;
p[1] = sub;
p[2] = mul;
p[3] = div;
p[4] = mod;
//第一种方法的循环
// int i;
// for(i = 0;i<5;i++)
// {
// printf("%d\n",p[i](a,b));
// }
//第二种方法:实现三位数相加的打印,(加减乘除取余的方法均可以用这种方法)
printf("%d\n",p[0](p[0](a,b),c));
return 0;
}
3.只读指针变量 ?? ?只读指着变量不能被重新赋值,地址不能被修改,但是值可以被修改 ?? ?定义:类型 ? *const ? 变量名
用const修饰的指针变量地址不能被修改,但是它所对应的地址的值可以被修改?
#include<stdio.h>
//只读指针变量 ,他这个地址只能被读不能被修改
int main()
{
// int *p;
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("%p\n",*p);
//只读指针的值可以被修改
*p = 100;
printf("%d\n",a);
printf("%p\n",p);
printf("%d\n",*p);
return 0;
}
4.只读变量指针 ?? ?只读变量指针,地址可以被修改,值不能被修改 ?? ?定义:类型 ?const ?* 变量名
//只读变量指针,与只读指针变量相反
//它的地址可以被修改,但是值只能读不可以改
#include<stdio.h>
int main()
{
int a = 20;
int b = 10;
//只读变量指针,从const往左看,休先结合int,说明是只读指针变量
int const * p = &a; //定义一个只读变量的指针
printf("%d\n",*p);
printf("%p\n",p);
printf("%d\n",a);
p = &b;//用const修饰的指针变量地址可以被修改,但是它所对应的地址的值被修改
printf("%d\n",*p);
printf("%p\n",p);
printf("%d\n",b);
printf("%d\n",a);
// *p = 200; // 不能修改只读变量指针的值
// printf("%d",*p);
// printf("%p",p);
// printf("%d",a);
return;
}
5.特殊指针 ?? ?1.硬编码赋值给指针 ?? ??? ?指针变量是指向变量的地址 ?? ??? ?这个没有意义,无法确定数值这个地址被占用,编译器会警告
int *p;
? 2.空指针 ?? ?一般用于初始化,不确定什么时候使用,所以先将他指向空值(NULL)
int *p = NULL;
?3.野指针 ?? ??? ?像上面2所说,如果定义了一个指针没有将他先指向空值(NULL),他会随机指向一个区域,通常将这个称为野指针。 ?? ??? ?指针被释放时没有将他置空,也会在下一步随机指向一个区域也称为野指针。比如:再用malloc( )函数开辟空间时,要检查返回值是否为空,如果为空,则开辟失败,如果不为空,则指针指向的是开辟的内存空间的首地址。指针指向的内存空间再用free()释放后,如果没有对释放后的指针进行置空,就会称为野指针。
#include<stdio.h>
#include<stdlib.h>
int main()
{
// int a = 10;//系统自动分配,申请空间在栈上
p = malloc(512);//需要程序员自己分配,用完释放掉,申请的空间在堆上
if(p == NULL)
{
return -1;
}
*p = 100;
printf("%d\n",*p);
free(p);
p = NULL;
return 0;
}
4.万能指针 ?void *(也称空类型指针) ?? ??? ?void *指针可以指向任意变量的内存空间
#include<stdio.h>
int main()
{
int a = 10;
char ch = 'a';
float b = 1.2;
void *pp;
pp = &a;
pp = &ch;
pp = &b;
// printf("%p\n",pp);
//printf("%d\n",*pp);//直接打印pp的值,会报错,因为pp是一个void型 的指针
// printf("%d\n",*((int *)pp));//将void *指针pp强制转换成某个数据类型的指针,再取值
//需要将void型的指针转换成int型指针在打印值
//通过万能指针修改变量内容值,需要指定变量对应的指针类型
*((int *)pp) = 100;
printf("%d\n",*((int *)pp));
*((char *)pp) = 'e';
printf("%c\n",*((char *)pp));
*((float *)pp) = 59.9;
printf("%f\n",*((float *)pp));
return 0;
}
|