一级指针传参:
void print(int* ptr, int sz)
{
int i = 0;
for (i = 0;i < sz;i++)
{
printf("%d ", *(ptr + i));
}
}
void test(char* p)//可以传什么参数?
{
}
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int* p = arr;
int sz = sizeof(arr) / sizeof(arr[0]);
//p是一级指针
print(p, sz);
char ch = 'w';
char* p1 = &ch;
test(&ch);//char*
test(p1);
return 0;
}
二级指针传参:
void test(int** p2)
{
**p2 = 20; //*p2是pa **pa是a
}
int main()
{
int a = 10;
int* pa = &a; //pa是一级指针
int** ppa = &pa; //ppa是二级指针
//把二级指针进行传参呢?
test(ppa);
test(&pa);//传一级指针变量的地址
int* arr[10] = { 0 };
test(arr);//能不能传arr过去呢???
//所以二级指针的传参是可以传存放一级指针数组的
printf("%d\n", a);
return 0;
}
总结下:
一级指针:
int* p; - 整形指针 - 指向整形的指针
char* pc; - 字符指针 - 指向字符的指针
void* pv; - 无类型的指针
二级指针: char**p; int**p;
数组指针:int(*p)[4]; - 指向数组的指针
函数指针:指向函数的指针!存放函数地址的指针
int Add(int x, int y)
{
return x + y;
}
int main()
{
int a = 10; //整形指针
int* pa = &a;
char ch = 'w'; //字符指针
char* pc = &ch;
int arr[10] = { 0 };
int(*parr)[10] = &arr;//取出数组的地址
//parr 是指向数组的指针 - 存放的是数组的地址
//函数指针 - 存放函数地址的指针
//&函数名 - 取到的就是函数的地址
printf("%p\n", &Add); //003C13BB
printf("%p\n", Add); //数组名 != &数组名;函数名 == &函数名
int (*pf)(int, int) = &Add; //pf是函数指针变量,但是类型是什么?
return 0;
}
那么函数指针的类型要怎么写呢?
void test(char* str)
{
}
int main()
{
pt = test;//pt是什么类型?? - void (*pt)(char*) = test;
return 0;
}
怎么调用函数指针呢?
int Add(int x, int y)
{
return x + y;
}
int main()
{
//int (*pf)(int, int) = &Add;
int (*pf)(int, int) = Add; //Add == pf
int ret = Add(3, 5); //这个是通过函数名的方式表示
int ret = (*pf)(3, 5);
int ret = pf(3, 5); //和上面的相同,所以得出*是个摆设,没有意义
//但如果不加括号,一定不能加星哦~
printf("%d\n", ret);
return 0;
}
代码解释:
(*(void (*)())0)(); //出自《C陷阱和缺陷》
意思是调用0地址处的函数
1.void(*)() - 函数指针类型;
2.(void(*)())0 - 对0进行强制装换类型,被解释为一个函数的地址
3. * (void(*)())0 - 对0地址处进行了解引用操作
4.(*(void (*)())0)() - 调用0地址处的函数
void(*signal(int, void(*)(int)))(int);
1.signal 和()先结合,说明signal是函数名
2.signal函数的第一个参数的类型是int,第二个参数的类型是函数指针
该函数指针,指向一个参数为int,返回类型是void的函数
3.signal函数的返回类型也是一个函数指针
该函数指针,指向一个参数为int,返回类型是void的函数
4.所以signal是一个函数的声明
void(*)(int) signal(int, void(*)(int));
这样写容易理解,但是语法不支持
所以怎么简化好呢?
可以这样简化:
typedef - 对类型进行重定义
typedef void(*pfun_t)(int);
pfun_t signal(int, pfun_t);
第一行代码的意思是对void(*)(int)的函数指针类型重命名为pfun_t
函数指针数组 - 存放函数指针的数组
整形指针 int*
整形指针数组 int* arr[5]
怎么写函数指针呢 ?
int Add(int x, int y)
{
return x + y;
}
int Sub(int x, int y)
{
return x - y;
}
int Mul(int x, int y)
{
return x * y;
}
int Div(int x, int y)
{
return x / y;
}
void menu()
{
printf("*********************************\n");
printf("******** 1.add 2.sub ********\n");
printf("******** 3.mul 4.div ********\n");
printf("********** 0.exit **********\n");
}
int main()
{
int (*pf1)(int, int) = Add;
int (*pf2)(int, int) = Sub;
int (*pfArr[2])(int, int) = { Add,Sub }; //函数指针数组
//实现一个计算器 - 计算器整形变量的加,减,乘,除
int input = 0;
do {
menu();
int x = 0;
int y = 0;
int ret = 0;
printf("请选择:>");
scanf("%d %d", &x, &y);
switch (input) //代码太多,怎么才能简化呢?
{ //可以用函数指针数组来简化
case 1:
printf("请输入2个操作数:>\n");
scanf("%d %d", &x, &y);
ret = Add(x, y);
printf("ret = %d\n", ret);
break;
case 2:
printf("请输入2个操作数:>\n");
scanf("%d %d", &x, &y);
ret = Sub(x, y);
printf("ret = %d\n", ret);
break;
case 3:
printf("请输入2个操作数:>\n");
scanf("%d %d", &x, &y);
ret = Mul(x, y);
printf("ret = %d\n", ret);
break;
case 4:
printf("请输入2个操作数:>\n");
scanf("%d %d", &x, &y);
ret = Div(x, y);
printf("ret = %d\n", ret);
break;
case 0:
printf("退出程序\n");
break;
default:
printf("选择错误,重新选择\n");
break;
}
} while (input);
return 0;
}
计算器简化版本:
#include <stdio.h>
int Add(int x, int y)
{
return x + y;
}
int Sub(int x, int y)
{
return x - y;
}
int Mul(int x, int y)
{
return x * y;
}
int Div(int x, int y)
{
return x / y;
}
void menu()
{
printf("*********************************\n");
printf("******** 1.add 2.sub ********\n");
printf("******** 3.mul 4.div ********\n");
printf("********** 0.exit **********\n");
}
int main()
{
//实现一个计算器 - 计算器整形变量的加,减,乘,除
int input = 0;
do {
menu();
int(*pfArr[5])(int, int) = { NULL,Add,Sub,Mul,Div };
int x = 0;
int y = 0;
int ret = 0;
printf("请选择:>");
scanf("%d", &input);
if (input >= 1 && input <= 4)
{
printf("请输入2个操作数:>\n");
scanf("%d %d", &x, &y);
ret = (pfArr[input])(x, y);
printf("ret = &d\n", ret);
}
else if(input == 0)
{
printf("退出程序\n");
break;
}
else
{
printf("选择错误\n");
}
} while (input);
return 0;
}
函数指针数组 - 数组
取出函数指针的地址
整形数组
int arr1[5];
int(*p1)[5] = &arr1;
整形指针数组
int* arr2[5];
int* (*p2)[5] = &arr2;
p2是指向【整数指针数组】的指针
函数指针数组
&函数指针数组
int (*p)(int, int); //函数指针
int(*p2[4])(int, int); //函数指针数组
int(*(*p3)[4])(int, int) = &p2; //取出的是函数指针数组的地址
p3就是以个指向【函数指针数组】的指针
回调函数:
定义:回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另外以个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或者条件发生时由另外一方调用的,用于对该事件或条件进行响应.
A函数 --传递-- B函数(A函数的地址)
A函数的指针
通过A函数的指针反回来调用A函数就是回调函数
例子:
那能不能把一个case里面的代码弄成一个函数呢?
可以是可以,但是很遗憾的是其他case语句不能用
但是实质是函数名不同(Add,Sub,Mul,Div),那我们能不能把它们作为一个函数参数传进来呢?
int Add(int x, int y)
{
return x + y;
}
int Sub(int x, int y)
{
return x - y;
}
int Mul(int x, int y)
{
return x * y;
}
int Div(int x, int y)
{
return x / y;
}
void menu()
{
printf("*********************************\n");
printf("******** 1.add 2.sub ********\n");
printf("******** 3.mul 4.div ********\n");
printf("********** 0.exit **********\n");
}
int Calc(int (*pf)(int)(int))
{
int x = 0;
int y = 0;
printf("请输入2个操作数:>");
scanf("%d %d", &x, &y);
return pf(x, y);
}
int main()
{
//实现一个计算器 - 计算器整形变量的加,减,乘,除
int input = 0;
do {
menu();
int ret = 0;
printf("请选择:>");
scanf("%d %d", &x, &y);
switch (input) //代码太多,怎么才能简化呢?
{ //可以用函数指针数组来简化
case 1:
ret = Calc(Add);
printf("ret = %d\n", ret);
break;
case 2:
ret = Calc(Sub);
printf("ret = %d\n", ret);
break;
case 3:
Calc(Div);
printf("ret = %d\n", ret);
break;
case 4:
Calc();
printf("ret = %d\n", ret);
break;
case 0:
printf("退出程序\n");
break;
default:
printf("选择错误,重新选择\n");
break;
}
} while (input);
return 0;
}