武邑网站建设代理,公司简介ppt模板免费,青岛中小微企业互联网站建设补贴,怎么建设国际网站首页目录#xff1a;一、函数指针1 函数类型2 函数指针(指向函数的指针)3 函数指针数组二.函数指针和指针函数比较1 定义不同2 写法不同3.用法不同三.函数指针做函数参数(回调函数)1 利用回调函数实现打印任意类型数据2 提供能够打印任意类型数组函数3 利用回调函数 提供查找功能四…目录一、函数指针1 函数类型2 函数指针(指向函数的指针)3 函数指针数组二.函数指针和指针函数比较1 定义不同2 写法不同3.用法不同三.函数指针做函数参数(回调函数)1 利用回调函数实现打印任意类型数据2 提供能够打印任意类型数组函数3 利用回调函数 提供查找功能四.练习一、函数指针1 函数类型通过什么来区分两个不同的函数一个函数在编译时被分配一个入口地址这个地址就称为函数的指针函数名代表函数的入口地址。函数三要素 名称、参数、返回值。C语言中的函数有自己特定的类型。这一点和数组一样因此我们可以用一个指针变量来存放这个入口地址然后通过该指针变量调用函数。注意通过函数类型定义的变量是不能够直接执行因为没有函数体。只能通过类型定义一个函数指针指向某一个具体函数才能调用。举例如下typedef int(p)(int, int);void my_func(int a,int b){printf(%d %d\n,a,b);
}void test(){p p1;//p1(10,20); //错误不能直接调用只描述了函数类型但是并没有定义函数体没有函数体无法调用p* p2 my_func;p2(10,20); //正确指向有函数体的函数入口地址
}2 函数指针(指向函数的指针)函数指针定义方式(先定义函数类型根据类型定义指针变量); typedef void(FUNC_TYPE)(int, char);先定义函数指针类型根据类型定义指针变量; typedef void( * FUNC_TYPE2)(int, char);直接定义函数指针变量; void(*pFunc3)(int, char) func;void func(int a, char c)
{printf(hello world\n);
}void test01()
{//1、先定义出函数类型再通过类型定义函数指针typedef void(FUNC_TYPE)(int, char);FUNC_TYPE* pFunc func;//pFunc(10, a);//2、定义出函数指针类型通过类型定义函数指针变量typedef void(*FUNC_TYPE2)(int, char);FUNC_TYPE2 pFunc2 func;//pFunc2(20, b);//3、直接定义函数指针变量void(*pFunc3)(int, char) func;pFunc3(30, c);
}个人理解和多维数组 中提到的数组指针非常类似定义也是三种形式。这里func是一个地址名称因此需要用一个地址名称去对等赋值。第一个方式定义普通类型需要将pFunc转换成地址形态去对等才有后面的写法pFunc(10, a)第二方式因为类型已经是指针类型定义出来的本来就是地址名称即指针变量因此直接对等第三种方式和第二种相同直接弄一个指针省略了再赋值地址名称。3 函数指针数组//函数指针的数组
void func1()
{printf(func1 调用了\n);
}void func2()
{printf(func2 调用了\n);
}void func3()
{printf(func3 调用了\n);
}void test02()
{void(*pArray[3])();pArray[0] func1;pArray[1] func2;pArray[2] func3;for (int i 0; i 3; i){pArray[i]();}
}二.函数指针和指针函数比较1 定义不同指针函数本质是一个函数其返回值为指针。函数指针本质是一个指针其指向一个函数。2 写法不同指针函数int* fun(int x,int y);函数指针int (*fun)(int x,int y);可以简单粗暴的理解为指针函数的*是属于数据类型的而函数指针的星号是属于函数名的。一个很简单的判定方法就是观察(*)记住其中一个即可int (*p)(int,int);有括号*与p结合*p就是个指针指向返回值为整型且有两个整型参数的函数的指针因此称为函数指针。int*p(int,int); 没有括号*与int结合int*为返回类型p就是一个函数名这时就是一个指针函数只不过返回值类型为int*。3 用法区别1指针函数指针函数的写法int *fun(int x,int y);
int * fun(int x,int y)
int* fun(int x,int y); //建议这种这个写法看个人习惯其实如果*靠近返回值类型的话可能更容易理解其定义。注意在调用指针函数时需要一个同类型的指针来接收其函数的返回值。也可以将其返回值定义为 void*类型在调用的时候强制转换返回值为自己想要的类型不过不建议这么使用因为强制转换可能会带来风险。typedef struct _Data {int a;int b;
}Data;//指针函数Data* f(int a, int b) {Data data {a, b};return data;
}int test02()
{Data* myData f(3, 5);printf(函数指针myData %d, b %d\n,myData-a, myData-b);
}2函数指针函数指针是需要把一个函数的地址赋值给它有两种写法funFunction
funFunction;取不是必需的因为一个函数标识符就表示了它的地址如果是函数调用还必须包含一个圆括号括起来的参数表。调用函数指针的方式也有两种x(*fun)();
xfun();两种方式均可其中第二种看上去和普通的函数调用没啥区别如果可以的话建议使用第一种因为可以清楚的指明这是通过指针的方式来调用函数。当然也要看个人习惯如果理解其定义随便怎么用都行啦。int add(int x, int y) {return x y;
}
int sub(int x, int y) {return x - y;
}
//函数指针
int test02()
{int (*fun)(int x, int y);//第一种写法fun add;printf((*fun)(5, 3) %d\n, (*fun)(5, 3));//第二种写法fun sub;printf((*fun)(5, 3) %d,(fun)(5, 3) %d\n,(*fun)(5, 3), fun(5, 3));}三.函数指针做函数参数(回调函数)函数参数除了是普通变量还可以是函数指针变量。函数指针变量常见的用途之一是把指针作为参数传递到其他函数指向函数的指针也可以作为参数以实现函数地址的传递。//形参为普通变量
void fun( int x ){}
//形参为函数指针变量
void fun( int(*p)(int a) ){}1 利用回调函数实现打印任意类型数据
//提供一个打印函数可以打印任意类型的数据
void printText(void* data, void(*myPrint)(void*))
{myPrint(data);
}void myPrintInt(void* data)
{int* num data;printf(%d\n, *num);
}void test01()
{int a 10;printText(a, myPrintInt);
}
void printText(void* data, void(*myPrint)(void*))
{myPrint(data);
}struct Person
{char name[64];int age;
};void myPrintPerson(void * data)
{struct Person * p data;printf(姓名 %s 年龄 %d\n, p-name, p-age);
}void test02()
{struct Person p { Tom, 18 };printText(p, myPrintPerson);
}2 提供能够打印任意类型数组函数//提供一个函数实现可以打印任意类型的数组
void printAllArray(void * pArray , int eleSize, int len , void(*myPrint)(void*) )
{char * p pArray;for (int i 0; i len;i){//获取数组中每个元素的首地址char * eleAddr p eleSize * i;//printf(%d\n, *(int *)eleAddr);//交还给用户做打印操作myPrint(eleAddr);}
}void myPrintInt(void * data)
{int * num data;printf(%d\n, *num);
}void test01()
{int arr[5] { 1, 2, 3, 4, 5 };int len sizeof(arr) / sizeof(int);printAllArray(arr, sizeof(int), len, myPrintInt);
}3 利用回调函数 提供查找功能struct Person
{char name[64];int age;
};void myPrintperson(void * data)
{struct Person * p data;printf(姓名%s 年龄%d \n, p-name, p-age);
}//查找数组中的元素是否存在
//参数1 数组首地址 参数2 每个元素的大小 参数3 数组元素个数 参数4 查找数据
int findArrayEle(void * pArray, int eleSize, int len, void * data , int(*myCompare)(void* ,void* ) )
{char * p pArray;for (int i 0; i len;i){//每个元素的首地址char * eleAddr p eleSize * i;//if ( 数组中的变量的元素 用户传入的元素)if ( myCompare(eleAddr,data) ){return 1;}}return 0;
}int myComparePerson(void * data1,void * data2)
{struct Person * p1 data1;struct Person * p2 data2;return strcmp(p1-name, p2-name) 0 p1-age p2-age;
}void test02()
{struct Person personArray[] {{ aaa, 10 },{ bbb, 20 },{ ccc, 30 },{ ddd, 40 },};int len sizeof(personArray) / sizeof(struct Person);printAllArray(personArray, sizeof(struct Person), len, myPrintperson);//查找数组中指定的元素是否存在struct Person p { ccc, 30 };int ret findArrayEle(personArray, sizeof(struct Person), len, p, myComparePerson);if (ret){printf(找到了元素\n);}else{printf(未找到\n);}
}四.练习提供一个函数实现对任意类型的数组进行排序排序规则利用选择排序排序的顺序 用户可以自己指定void selectSort(void* pAddr, int elesize, int len, int(*myCompare)(void*, void*))
{char* temp malloc(elesize);for (int i 0; i len; i){int minOrMax i; //定义最小值 或者 最大值 下标for (int j i 1; j len; j){//定义出 j元素地址char* pJ (char*)pAddr elesize * j;char* pMinOrMax (char*)pAddr elesize * minOrMax;//if ( pAddr[j] pAddr[minOrMax])/* 从大到小if ( *num1 *num2){return 1;}return 0;*/if (myCompare(pJ, pMinOrMax)){minOrMax j; //更新最小值或者最大值下标}}if (i ! minOrMax){//交换i和minOrMax 下标元素char* pI (char*)pAddr i * elesize;char* pMinOrMax (char*)pAddr minOrMax * elesize;memcpy(temp, pI, elesize);memcpy(pI, pMinOrMax, elesize);memcpy(pMinOrMax, temp, elesize);}}if (temp ! NULL){free(temp);temp NULL;}}int myCompareInt(void* data1, void* data2)
{int* num1 data1;int* num2 data2;if (*num1 *num2){return 1;}return 0;
}void test01()
{int arr[] { 10, 30, 20, 60, 50, 40 };int len sizeof(arr) / sizeof(int);selectSort(arr, sizeof(int), len, myCompareInt);for (int i 0; i len; i){printf(%d\n, arr[i]);}
}struct Person
{char name[64];int age;
};int myComparePerson(void* data1, void* data2)
{struct Person* p1 data1;struct Person* p2 data2;//if ( p1-age p2-age)//{// return 1;//}//return 0;//按照年龄 升序排序return p1-age p2-age;
}void test02()
{struct Person pArray[] {{ aaa, 10 },{ bbb, 40 },{ ccc, 20 },{ ddd, 30 },};int len sizeof(pArray) / sizeof(struct Person);selectSort(pArray, sizeof(struct Person), len, myComparePerson);for (int i 0; i len; i){printf(姓名%s 年龄:%d\n, pArray[i].name, pArray[i].age);}
}