网站开发实训新的体会,有哪些公司做网站,海外网站建站,禹州市城乡建设局网站目录
函数指针
函数名和函数名
函数指针的定义
函数指针的使用
函数指针陷阱
代码1
代码2
注意
函数指针数组定义
函数指针数组的使用
指向函数指针数组的指针
书写 终于军训圆满结束了#xff0c;首先回顾一下指针进阶篇#xff08;1#xff09;主要是…目录
函数指针
函数名和函数名
函数指针的定义
函数指针的使用
函数指针陷阱
代码1
代码2
注意
函数指针数组定义
函数指针数组的使用
指向函数指针数组的指针
书写 终于军训圆满结束了首先回顾一下指针进阶篇1主要是指针数组的点
C语言之指针进阶篇1_唐棣棣的博客-CSDN博客https://blog.csdn.net/m0_74841364/article/details/132223126?spm1001.2014.3001.5502今天我们继续更深入的来了解指针主要是指针函数数组的点
函数指针
在前面我们已经了解过字符指针数组指针这里我们将介绍到函数指针 指针数组——是数组是存放指针的数组。 数组指针——是指针指向数组的指针。 字符指针——指向字符的指针。 整型指针——指向整型的指针。 浮点型的指针——指向浮点型的指针。 函数指针——指向函数的指针。 函数名和函数名
类比数组指针。 数组指针——指向数组的指针——存放的是数组的地址——数组名就是数组的地址 函数指针——指向函数的指针——存放的是函数的地址——函数地址是否是函数名呢 那我们用代码来验证下。
#includestdio.h
int Add(int x, int y)
{return x y;
}
int main()
{//int x 0;//int y 0;//scanf(%d %d, x, y);printf(%p\n, Add);printf(%p\n, Add);//函数名 就是函数的地址//函数名 也是函数的地址//注意函数名并没有首元素这一说法
} 函数名和函数名都是函数的地址。 那它们是否有什么区别和它们的类型是一样的吗 它们没有区别知识写法不一样。 它们两个类型是一样的。指向同一个函数类型是相同的。 整形函数指针类型 函数指针的定义 如果在程序中定义了一个函数那么在编译时系统就会为这个函数代码分配一段存储空间这段存储空间的首地址称为这个函数的地址。而且函数名和函数名均表示的就是这个地址。既然是地址我们就可以定义一个指针变量来存放这个指针变量就叫作函数指针变量简称函数指针。 那该怎样去写函数指针呢 #includestdio.h
int Add(int x, int y)
{return x y;
}
int main()
{printf(%p\n, Add);printf(%p\n, Add);int (*p)(int,int) Add;//更容易理解和熟悉int (*p)(int x,int y) Add;int (*p)(int x,int y) Add;//写不写x y都可int (*p)(int,int) Add;
//和x y 写不写都可
}
这个语句就定义了一个指向函数的指针变量 p。
首先它是一个指针变量所以要有一个“*”即*p
其次前面的 int 表示这个指针变量可以指向返回值类型为 int 型的函数
后面括号中的两个 int 表示这个指针变量可以指向有两个参数且都是 int 型的函数。
所以合起来这个语句的意思就是
定义了一个指针变量 p该指针变量可以指向返回值类型为 int 型且有两个整型参数的函数。
p 的类型为 int(*)(intint)。 int *p) (int, int); 函数返回值类型 (* 指针变量名) (函数参数列表); 定义了一个指针变量 p该指针变量可以指向返回值类型为 int 型且有两个整型参数的函数。p 的类型为 int(*)(intint)。 p就是函数指针变量。 那如果写成int* p(int,int);? *和int 结合 int* 变成了函数声明了。 函数指针的使用
函数指针的使用最长应用在转移表和回调函数 那我们在接下来的文章都会讲到。
#includestdio.h
int Add(int x, int y)
{return x y;
}
int main()
{printf(%p\n, Add);printf(%p\n, Add);int (*p)(int,int) Add;int ret(*p)(3, 5);//解引用找到函数int ret (********p)(3, 5);//*是个摆设写不写都可int ret Add(3, 5);//直接调用Add函数就是用Add函数的地址int ret p(3, 5);//这里也可以直接使用地址printf(%d, ret);
}
我们有以上三种写法去调用函数 Add,但是我们不可以乱写哦 int ret* p(3, 5);
函数指针陷阱
阅读两段有趣的代码 我们改怎样去理解这两端代码呢
代码1
(*(void (*)())0)();
//函数调用
图错误待修改 在调用 0地址处的函数这个函数没有参数返回类型是void把0从int类型强制转化成函数指针类型指向了0处的地址处的函数
代码2
void (*signal(int , void(*)(int)))(int);
//函数声明图错误待修改 这个代码是一次函数声明声明的是signal函数signal函数有两个参数一个是int类型一个是函数指针类型该类型是void (*)(int)函数指针类型 该函数指针指向的函数参数是int, 返回类型是voidsignal函数的返回类型也是函数指针类型该类型是void (*) (int)函数指针类型 该函数指针指向的函数参数是int, 返回类型是void
代码2太复杂了那能不能简化代码2当然可以。
void (* signal(int, void(*)(int)))(int);
//void(*)(int) signal(int void(*)(int));❌
//重定义
typedef void(*pfun_t)(int);
pfun_t signal(int pfun_t);
注 :推荐《C陷阱和缺陷》
注意
函数指针变量函数指针函数指针类型函数指针类型 修饰一个 函数指针变量可以是函数等 / 也可以没有/或者 将其他类型强制转化成函数指针类型 意味着则该函数指针指向一个 返回类型是参数是的函数函数指针定义 int(*p)(int,int)Add; 函数指针调用 (*p)(3,5);
p(3,5);
(*p)();
p();//不传参数 函数指针声明 void (* signal(int,int))(int); 函数指针类型和函数指针变量的写法 int(*p)(int,int);
void(*p)(int);
函数指针数组定义 char * arr[5]字符指针数组——数组——存放的是字符指针 int * arr[5]整形指针数组——数组——存放的是整形指针 int(*p[5])(int,int) void(*p[5])(int,char)等等 函数指针数组——数组——存放的是函数指针函数的地址 把函数的地址存到一个数组中那这个数组就叫函数指针数组那函数指针的数组如何定义呢
int (*parr1[10]])();
int *parr2[10]();
int (*)() parr3[10] 答案是parr1 parr1 先和 [] 结合说明parr1是数组。 数组的内容是什么呢 是 int (*)() 类型的函数指针。 #includestdio.h
int Add(int x, int y)
{return x y;
}
int Sub(int x, int y)
{return x - y;
}
int main()
{int(*p1)(int, int) Add;int(*p1)(int, int) Sub;//函数指针数组中存放的类型相同的多个元素int(*p[])(int, int) { Add,Sub };//p是函数指针数组_存放函数指针的数组//均是返回类型为int,函数参数是int,int类型
}
函数指针数组的使用
函数指针数组的用途转移表。
使用条件函数类型/函数参数类型必须一摸一样
#define _CRT_SECURE_NO_WARNINGS 1
//计算器
#includestdio.h
void meau()
{printf(**************************\n);printf(** 1.add 2.sub ****\n);printf(** 3.mul 4.div ****\n);printf(** 0.exit *****\n);printf(**************************\n);
}
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;
}
int main()
{int input 0;int x 0;int y 0;int ret 0;do{meau();printf(请选择);scanf(%d, input);switch (input){case 1:printf(请输入2个操作数);scanf(%d %d, x, y);ret Add(x, y);printf(ret%d\n, ret);break;case 2:printf(请输入2个操作数);scanf(%d %d, x, y);ret Sub(x, y);printf(ret%d\n, ret);break;case 3:printf(请输入2个操作数);scanf(%d %d, x, y);ret Mul(x, y);printf(ret%d\n, ret);break;case 4:printf(请输入2个操作数);scanf(%d %d, x, y);ret Div(x, y);printf(ret%d\n, ret);break;case 0:printf(退出游戏);break;default:printf(选择错误重新选择\n);break;}} while (input);return 0;
} 能不能让代码变得简单一点
//简化后
#includestdio.h
void meau()
{printf(**************************\n);printf(** 1.add 2.sub ****\n);printf(** 3.mul 4.div ****\n);printf(** 0.exit *****\n);printf(**************************\n);
}
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;
}
int main()
{int input 0;int x 0;int y 0;int ret 0;//用函数指针数组//do{meau();printf(请选择\n);scanf(%d, input);int(*p[])(int, int) { NULL,Add,Sub,Mul,Div };//0 1 2 3 4if (input 0)printf(退出游戏\n);else if (input 0 input 4){printf(请输入两个操作数\n);scanf(%d %d, x, y);ret (*p[input])(x, y);printf(ret%d\n, ret);// ret p[input](x, y);//用函数指针数组的下标找到指向的函数}else//其他printf(选择错误请重新选择\n);} while (input);return 0;
} 当然出了使用函数指针数组去更高效的使用计算器下章我们将使用回调函数去高效优化计算器
指向函数指针数组的指针 指向函数指针数组的指针是一个 指针 指针指向一个 数组 数组的元素都是 函数指针 。 指向整型指针数组的指针
#includestdio.h
int main()
{int a 0;int b 0;int c 0;int* arr[] { a,b,c };//整形指针数组int* (*p)[3] arr;//p是指针是指向整形指针数组的指针return 0;
}
函数指针数组的指针
#includestdio.h
int main()
{int(*arr[5])(int, int) { NULL,Add,Sub,Mul,Div };p arr;//存放函数指针数组的指针int(*(*p)[5])(int, int) arr;return 0;
}
书写
无论是函数指针函数指针数组函数指针数组的指针等等可以一直延申下去
我们在书写变量是首先将变量p写出来在添加其类型。
也可以从简单的函数指针的基础上修改
✔✔✔✔✔最后感谢大家的阅读若有错误和不足欢迎指正最近的心情多做事少说话。
代码------→【gitee:https://gitee.com/TSQXG】
联系------→【邮箱2784139418qq.com】