C基础梳理 2019.1.4(函数指针,函数指针数组,宏,利用预定义宏输出是哪个文件的哪一行出错了)

函数指针

 

函数名就是函数的入口地址

通过获取函数入口的地址,利用函数指针,也可以调用函数。例子如下(代码中的地址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;
    }
}

 

 

条件编译

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值