重庆选科网站,北京网站建设降龙网络,商业网站模板,建筑工程网上备案流程文章目录 一、前言二、指针函数2.1 概念2.2 定义2.3 具体例子 三、函数指针3.1 概念3.2 定义3.3 具体例子3.4 回调函数3.4.1 概念3.4.2 例子13.4.3 例子2 四、函数指针数组4.1 概念4.2 定义4.3 具体例子 五、函数指针数组的指针5.1 概念5.2 定义5.3 具体例子 一、前言
关于指针… 文章目录 一、前言二、指针函数2.1 概念2.2 定义2.3 具体例子 三、函数指针3.1 概念3.2 定义3.3 具体例子3.4 回调函数3.4.1 概念3.4.2 例子13.4.3 例子2 四、函数指针数组4.1 概念4.2 定义4.3 具体例子 五、函数指针数组的指针5.1 概念5.2 定义5.3 具体例子 一、前言
关于指针和函数文章从有两方面入手一方面是将指针作为实参传给函数另一方面则是函数指针这一类函数和指针结合的数据类型。
科普
函数名本质上是函数的地址其用法跟数组名类似。
二、指针函数
2.1 概念
指针函数本质上是一个函数此函数返回一个指针。
2.2 定义
char *func(char a, char b){}2.3 具体例子
在函数指针的使用中大多数情况下需要动态分配内存来存放返回的数据。如果使用局部变量当函数运行结束后局部变量会被释放上层代码访问时可能会导致非法访问从而引发程序段错误。
#include stdio.h
#include stdlib.h
#include string.hchar *my_strcat(char *str1, char *str2)
{char *p NULL;char *p1 NULL;char *ptemp NULL;/* 动态内存分配 */p (char *)malloc(20 * sizeof(char));if(!p){return NULL;}p1 p;ptemp str1;while(*ptemp ! \0){*p1 *ptemp;}ptemp str2;while(*ptemp ! \0){*p1 *ptemp;}*p1 \0;printf(p%s\n, p);return p;
}int main()
{char str1[10] hello ;char str2[10] world!;char *return_str NULL;return_str my_strcat(str1, str2);printf(return str[%s]\n, return_str);if(return_str)free(return_str);return 0;
}三、函数指针
3.1 概念
函数指针本质是一个指针它指向一个函数的地址通过它来调用函数。
3.2 定义
首先定义一个函数
int add(int x, int y){}此时函数的地址就是函数名。我们声明一个函数指针并把函数的地址赋值给这个函数指针。这里要注意定义的函数和声明的函数指针的参数列表应该保持一致。
int (*pf)(int, int) add;下面让我们看一个表达式
(*(void(*)())0)();这一行代码的意思是调用0地址处的函数该函数无参返回类型是void。
我们再来看一下signal函数的原型
void (*signal(int, void(*)(int)))(int); 函数名signal
两个参数int和void(*)(int) 第二个参数也是一个函数指针
返回值void(*)(int)函数指针
这样看起来很复杂我们可以使用typedef来简化表达。
首先我们可以把signal函数的原型写成
void(*)(int) signal(int, void(*)(int));但是这种结构语法是不允许C语言的语法要求函数的返回类型必须明确地写在函数名之前。接下来我们使用typedef简化。
typedef void(*pfun_t)(int);//void(*)(int) pfun_t
pfun_t signal(int, pfun_t);//pfun_t - void(*)(int)3.3 具体例子
int add(int a, int b) { return a b; }int main()
{int (*pf)(int, int) add;int ret pf(3,5);printf(ret%d\n, ret);return 0;
}3.4 回调函数
3.4.1 概念
回调函数是一种通过函数指针调用的函数。
3.4.2 例子1
Handle函数第二个参数是该函数的首地址把这个首地址用函数指针接收int (*Callback)(int)在Handle函数中使用这个首地址Callback(x)这时就会运行主函数Handle第二个参数的函数。
int Callback_1(int a) /// 回调函数1
{printf(Hello, this is Callback_1: a %d , a);return 0;
}int Callback_2(int b) /// 回调函数2
{printf(Hello, this is Callback_2: b %d , b);return 0;
}int Callback_3(int c) /// 回调函数3
{printf(Hello, this is Callback_3: c %d , c);return 0;
}int Handle(int x, int (*Callback)(int)) /// 注意这里用到的函数指针定义
{Callback(x);
}int main()
{Handle(4, Callback_1);Handle(5, Callback_2);Handle(6, Callback_3);return 0;
}3.4.3 例子2
这是一个常用在工作中的使用形式。M26_WorkStatus_TypeDef的第二个参数保存的函数的首地址。
/********* 工作状态处理 *********/
typedef struct
{uint8_t mStatus;uint8_t (* Funtion)(void); //函数指针的形式
} M26_WorkStatus_TypeDef; //M26的工作状态集合调用函数/**********************************************
** M26工作状态集合函数
***********************************************/
M26_WorkStatus_TypeDef M26_WorkStatus_Tab[]
{ {GPRS_NETWORK_CLOSE, M26_PWRKEY_Off }, //模块关机{GPRS_NETWORK_OPEN, M26_PWRKEY_On }, //模块开机{GPRS_NETWORK_Start, M26_Work_Init }, //管脚初始化{GPRS_NETWORK_CONF, M26_NET_Config }, //AT指令配置{GPRS_NETWORK_LINK_CTC, M26_LINK_CTC }, //连接调度中心 {GPRS_NETWORK_WAIT_CTC, M26_WAIT_CTC }, //等待调度中心回复 {GPRS_NETWORK_LINK_FEM, M26_LINK_FEM }, //连接前置机{GPRS_NETWORK_WAIT_FEM, M26_WAIT_FEM }, //等待前置机回复{GPRS_NETWORK_COMM, M26_COMM }, //正常工作{GPRS_NETWORK_WAIT_Sig, M26_WAIT_Sig }, //等待信号回复{GPRS_NETWORK_GetSignal, M26_GetSignal }, //获取信号值{GPRS_NETWORK_RESTART, M26_RESET }, //模块重启
}
/**********************************************
** M26模块工作状态机依次调用里面的12个函数
***********************************************/
uint8_t M26_WorkStatus_Call(uint8_t Start)
{uint8_t i 0;for(i 0; i 12; i){if(Start M26_WorkStatus_Tab[i].mStatus){ return M26_WorkStatus_Tab[i].Funtion();}}return 0;
}四、函数指针数组
4.1 概念
函数指针数组本质是一个数组数组中存放的函数指针。
4.2 定义
int (*pfArr[2])(int, int);在函数指针的基础上在函数名后面加上[]。
4.3 具体例子
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 division(int a, int b) { return a / b; }int main()
{/* 模拟键盘输入 */int input 2;int ret;int (*pf[5])(int, int) {NULL, add, sub, mul, division};ret pf[input](3,5);printf(ret%d\n, ret);return 0;
}五、函数指针数组的指针
5.1 概念
函数指针数组的指针本质上是一个指针指向一个函数指针数组。
5.2 定义
int(* (*p3)[4])(int, int);在函数指针数组的基础上在函数名前面加上*号并用小括号括起来。
5.3 具体例子
在这里面一定是pf才行因为p1是指向数组的指针而不是指向数组首地址的指针我们应该使用把数组的地址取出来。
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 division(int a, int b) { return a / b; }int main()
{/* 模拟键盘输入 */int input 2;int ret;int (*pf[5])(int, int) {NULL, add, sub, mul, division};int (*(*p1)[5])(int, int) pf;ret (*p1)[input](3,5);printf(ret%d\n, ret);return 0;
}