函数指针、函数指针数组、指向函数指针数组的指针

建议在看函数指针前,了解一下数组指针,指针数数组的解析,假如本来就了解的化就可跳过。

点击打开链接

一、函数指针(本质是指针

其实函数的函数名也是一个地址,就像数组名一样,但&函数名,和函数名单独使用在函数指针时是一样的。

可以实践一下,代码如下。

void test()
{
	printf("好好学习,天天编程\n");
}

int main()
{
	printf("%p", test);
	system("pause");
	return 0;
}


那么它肯定可以也有像数组指针一样的类型函数指针。

void (*pfun)();//定义函数指针     void()() 函数声名后面一个括号里放的是参数列表。变量pfun先和*结合,本质是指针。然后                                                才是void()()函数声名。  则这就是一个函数指针,指针指向的函数无参数,返回值类型为void型。

pfun=test;//把函数的地址赋给函数指针pfun

也可以写成 pfun=&test;

既然知道了函数指针,那么辨析以下有趣的代码。

1.( * ( void( * )( ) )0)( ) ;

括号拆分法(*(void(*) ( ) ) 0 )( );

这是《CTraps and Pitfalls》这本经典的书中的一个例子。没有发狂吧?下面我们就来分 析分析:
第一步:void(*)(),可以明白这是一个函数指针类型。这个函数没有参数,没有返回值。
第二步:(void(*)())0,这是将 0 强制转换为函数指针类型,0 是一个地址,也就是说一 个函数存在首地址为 0 的一段区域内。
第三步:(*(void(*)())0),这是取 0 地址开始的一段内存里面的内容,其内容就是保存 在首地址为 0 的一段区域内的函数。

第四步:(*(void(*)())0)(),这是函数调用。

2.void( * signal ( int,void( * )( int ) ) )( int )

同样也用括号拆分法void * signal ( int,void( * )( int ) ) )( int )

第一步:signal ( int,void( * )( int ) ),可以明白signal是一个函数名,它有两个参数一个是int,一个是一个void( * )( int )函数指针,且该函数指针指向的是一个匿名函数,该函数参数为int,返回值类型为void型。

第二步:void( * signal ( int,void( * )( int ) ) )( int ),去掉已分析过的黄色部分,可以明白signal函数的返回类型为函数指针类型          void( *                                           )( int ),该返回类型(函数指针)指向的是一个匿名函数,该函数参数为int,返回值类型为void型。

函数指针本质是指针,指针指向的函数由修饰指针的类型所决定。

二、函数指针数组 (本质是数组

既然有函数指针,那么就有函数指针数组(与指针数组对比)

int ( *  parr [10] )( )

parr与[]先结合,所以本质是数组,数组中存放的是函数指针

函数指针数组的用途:转移表

#include <stdio.h> 
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 div(int a, int b) 
{         
	return a / b;
} 
int main() 
{    
	int x, y;     
	int input = 1;   
	int ret = 0; 
	int(*p[5])(int x, int y) = { 0, add, sub, mul, div }; // 转移表     
	while (input)    
	{          
		printf( "*************************\n" );         
		printf( "  1:add           2:sub  \n" );       
		printf( "  3:mul           4:div  \n" );       
		printf( "*************************\n" );       
		printf( "请选择:" );          
		scanf( "%d", &input);         
		if ((input < 4 && input > 1))          
		{              
			printf( "输⼊入操作数:" );             
			scanf( "%d %d", &x, &y);              
			ret = (*p[input])(x, y);         
		}          
		else              
			printf( "输⼊入有误\n" );         
		printf( "ret = %d\n", ret);    
	}      
	return 0; 
}

三、指向函数指针数组的指针(本质上是一个指针)

void test(const char* str) 
{
	printf("%s\n", str); 
} 
int main() 
{   
	// 函数指针 pfun    
	void (*pfun)(const char*) = test;    
	// 函数指针的数组 pfunArr    
	void (*pfunArr[5])(const char* str);   
	pfunArr[0] = test;  
	// 指向函数指针数组 pfunArr 的指针 ppfunArr    
	void (*(*ppfunArr)[10])(const char*) = &pfunArr; 
	return 0; 
}

void (* (*ppfunArr)[10] )(const char*)

指针指向一个数组,数组中的每一个元素都是函数指针。

4.回调函数

回调函数就是⼀一个通过函数指针调⽤用的函数。如果你把函数的指针(地址)作为参数传递给 另⼀一个函数,当这个指针被⽤用来调⽤用其所指向的函数时,我们就说这是回调函数。回调函数 不不是由该函数的实现⽅方直接调⽤用,⽽而是在特定的事件或条件发⽣生时由另外的一一⽅方调⽤用的,⽤用于对该事件或条件进⾏行行响应。

目前对函数指针的了解大概就这么多,如果学到新的内容会随时更新的。

猜你喜欢

转载自blog.csdn.net/SoYangA/article/details/80634396