函数指针
函数名就是函数的入口地址
通过获取函数入口的地址,利用函数指针,也可以调用函数。例子如下(代码中的地址4195554是之前获取到的):
#include<stdio.h>
void func(){
printf("hello word!");
}
int main(){
printf("函数入口地址:%d\n", func);
int *funcAddr=(int*)4195554;
//定义函数指针
void(*myfunc)()=funcAddr;
myfunc();
return 0;
}
如何去定义一个指向函数的指针
函数是由返回值类型和参数列表组成,为什么没有函数名,因为函数名可变。
方法一:定义函数类型,通过类型定义函数指针
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
//如何去定义一个指向函数的指针
int myfunc(int a, char b){
printf("int myfunc(int a, char b)");
return 0;
}
void test(){
//定义函数类型,通过类型定义函数指针
typedef int (FUN_TYPE)(int, char);
FUN_TYPE *pFunc=myfunc;
//三种调用mufunc的方式
pFunc(10, 'a');
(*pFunc)(20, 'b');
myfunc(30, 'c');
}
int main(){
test();
return 0;
}
运行结果
方法二:直接定义函数指针类型
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
void func(){
printf("hello word!");
}
//如何去定义一个指向函数的指针
int myfunc(int a, char b){
printf("int myfunc(int a, char b)");
return 0;
}
void test(){
//直接定义函数指针类型
typedef int(*FUNC_P)(int, char);
FUNC_P pFunc2=myfunc;
pFunc2(20, 'd');
//c语言中类型检查不是特别严格
//下面这句也不会报错,我们尽量让函数指针指向同类型
//pFunc2=func;
}
int main(){
test();
return 0;
}
方法三:直接定义函数指针变量
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
void func(){
printf("hello word!");
}
//如何去定义一个指向函数的指针
int myfunc(int a, char b){
printf("int myfunc(int a, char b)");
return 0;
}
void test(){
//直接定义函数指针变量
//指针转化成函数指针类型的写法
int (*pFunc3)(int, char)=(int(*)(int, char))NULL;
pFunc3=myfunc;
pFunc3(50, 'p');
printf("pFunc3 size:%d\n",sizeof(pFunc3));
}
int main(){
test();
return 0;
}
运行结果
(64位的虚拟机,所以指针大小都是8)
函数指针可以指向多个函数,你要调用哪个函数你要指定一下。不然不知道你要调用的是谁。
函数指针数组
void func1(){}
void func2(){}
void func3(){}
void(*func_array[3])();
func_array[0]=func1;
func_array[1]=func2;
func_array[2]=func3;
//函数调用
for(int i=0; i<3; i++){
func_array[i]();
}
函数指针做函数参数(回调函数)
//传入函数指针数组,我们并不知道函数的类型,因此也不知道要写什么返回值
//因此返回值定义为void,让用户自己去写返回的函数
//第二个参数是每个数组元素的大小
void print(void* arr, int eleSize, int len){
char *start=(char*)arr;
for(int i=0; i<len; i++){
printf("%d\n", start+i*eleSize);
}
}
//传入的第四个参数是一个函数指针
//调用这个函数的时候,把我们的函数名写在第四个参数的位置,即可达到调用函数的作用
void printAllArray(void* arr, int eleSize, int len, void(*print)(void *)){
char *start=(char*)arr;
for(int i=0; i<len; i++){
//指针指向每个函数的地址
char *eleAddr = start+i*eleSize;
//把函数地址传给print函数指针
print(eleAddr);
}
}
int main(){
int arr[]={1,2,3,4,5};
//MyPrint是我们写的函数
printAllArray(arr, sizeof(int), 5, MyPrint);
}
宏
宏定义,只在宏定义的文件中起作用。
利用预定义宏输出是哪个文件的哪一行出错了
void ppp(int *p){
if(p==NULL){
//输出哪个文件,哪一行报错
//利用了预定义的宏
printf("%s的%d行出错!\n", __FILE__, __LINE__);
printf("%s\n", __DATE__);
printf("%s\n", __TIME__);
return;
}
}