关于typedef函数指针的用法和理解

  • Post author:
  • Post category:其他


                                   关于typedef函数指针的用法和理解         

在此记录下所理解的和具体用法,以防忘记了又重复找资料。。。属于找到资料后的总结,如果有错误的理解,还望提出


1、什么是函数指针


如果在程序中定义了一个函数,那么在编译时系统就会为这个函数代码分配一段存储空间,这段存储空间的首地址称为这个函数的地址。而且函数名表示的就是这个地址。既然是地址我们就可以定义一个指针变量来存放,这个指针变量就叫作函数指针变量,简称函数指针。

函数指针的定义方式为: 函数返回值类型 (* 指针变量名) (函数参数列表);

例如 int(*p)(int, int);

注意的是,指向函数的指针变量没有 ++ 和 – – 运算

简单用法:

int fun(int x); //声明一个函数

int (*p) (int x); //定义一个函数指针

p = Func; //将Func函数的首地址赋给指针变量p

这个其实感觉和数组差多,int a[10]; int * p ; p = a;——-自我感觉可以结合起来一起记


2、用typedef来定义类型使用


2.1 最简单的用法

形式1:typedef 返回类型(*新类型)(参数表)

typedef char (*PTRFUN)(int); 
PTRFUN pFun; 
char Fun(int a){ return;} 
void main() 
{ 
    pFun = Fun; 
    (*pFun)(2); //pFun(2);这样写也可以编译通过并正确
}

typedef的功能是定义新的类型。第一句就是定义了一种PTRFUN的类型,PTRFUN这个类型定义出来的变量将会是一个

拥有int类型为参数并返回char类型的函数的

指针。 第二行的代码使用这个新类型定义了变量pFun.第三行的代码是实现了一个函数Fun。最后在main函数里面直接像变量赋值一样给pFun赋值Fun。

2.2大佬的例子(这个列子就当学习怎么使用typedef了,底部有链接地址可以去看他的文章):

#include <stdio.h>
#include <assert.h>
 
typedef int (*FP_CALC)(int,int);//定义一个函数指针类型
 
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 b ? a/b : -1;
}

//定义一个函数,参数为op,返回一个指针,该指针类型为拥有两个int参数、返回类型为int的函数指针。它的作用是根据操作符返回相应函数的地址

FP_CALC calc_func(char op)
{
	switch( op )
	{
	case '+':
		return add;
	case '-':
		return sub;
	case '*':
		return mul;
	case '/':
		return div;
	default:
		return NULL;
	}
	return NULL;
}

//s_calc_func为函数,它的参数是 op, 返回值为一个拥有两个int参数、返回类型为int的函数指针

int (*s_calc_func(char op)) (int , int)
{
	return calc_func(op);
}

//最终用户直接调用的函数,该函数接收两个int整数,和一个算术运算符,返回两数的运算结果

int calc(int a, int b, char op)
{
	FP_CALC fp = calc_func(op);
	int (*s_fp)(int,int) = s_calc_func(op);//用于测试
 
	assert(fp == s_fp);// 可以断言这两个是相等的
 
	if(fp)
		return fp(a,b);
	else
		return -1;
}
 
void main()
{
	int a = 100, b = 20;
 
	printf("calc(%d, %d, %c) = %d\n", a, b, '+', calc(a, b, '+'));
	printf("calc(%d, %d, %c) = %d\n", a, b, '-', calc(a, b, '-'));   
    printf("calc(%d, %d, %c) = %d\n", a, b, '*', calc(a, b, '*'));   
    printf("calc(%d, %d, %c) = %d\n", a, b, '/', calc(a, b, '/')); 
}

2.3 最后在来一个不好理解的例子,在上一个例子的基础上在加了一点

我们要申明一个这样的函数:

void (*signal( int, void(*)(int) ) (int);

这个可以分为2部分来看 ,将

signal( int, void(*)(int) )

用 p 代替,则变成了

void(*p)(int);

这样看起来是不是就很清晰了,不过这时候一定要注意p是函数,void(*) (int)是这个函数的返回值,
千万不要把p认为是函数指针了,函数p的返回值为一个拥有1个int参数、返回类型为void的函数指针。
然后我们再来看signal( int, void(*)(int) ) ,signal是一个拥有2个参数的函数,一个参数是int,
另外一个参数比较特殊,是一个拥有1个int参数、返回类型为void的函数指针。

我们再用typedef简化上面的函数申明:

typedef void*HANDLER)(int);
HANDLER signal(int,HANDLER);


补充

:其实要理解typedef函数指针的用法,更应该要去理解函数申明


(*(void(*) ())0)()

——这是什么?

我最初看到也是想都不想去理解,因为我觉得我就用不到,不过我们老大说知识要理解透彻,这样才能不至于2~3年后就走到了瓶颈,就试着去看完了文档的讲解,说了一大篇。这里贴上网上大佬的讲解。

这是《C Traps and Pitfalls》这本经典的书中的一个例子。分析:

第一步:

void(*) ()

,可以明白这是一个函数指针类型。这个函数没有参数,没有返回值。

第二步:

(void(*) ())0

,这是将0强制转换为函数指针类型,0是一个地址,也就是说一个函数存在首地址为0的一段区域内。

第三步:

(*(void(*) ())0)

,这是取0地址开始的一段内存里面的内容,其内容就是保存在首地址为0的一段区域内的函数。

第四步:

(*(void(*) ())0)()

,这是函数调用。

借鉴网址:

https://blog.csdn.net/u012654205/article/details/95593808 typedef 用法(定义数据 定义函数 基础)

https://blog.csdn.net/qll125596718/article/details/6891881?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-2.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-2.control (这网址有毒吧,这样长)

https://www.cnblogs.com/haore147/p/3647262.html c语言函数指针的理解与使用



版权声明:本文为qq_21805743原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。