c难于理解的是指针,其魅力之处也是指针,函数方法结构,化繁为简可以理解为:返回值 函数名(形参表),具体来说:
返回值:1.可以为空void
2.基本数据类型char short int long float double
3.指针
形参表跟返回值一样,这里面最复杂最难理解的是指针,因为指针本身是一个变量,里面保存的是地址,而地址的类型是由指针定义的时候申明的,而指针又可以指向函数,这样一搭配就非常复杂了。我们从一个复杂的程序开始:
void(*signal(int sig_num,void(*handler)(int)))(int)
第一看到都会头晕,不过抽丝剥茧之后发现也就那么回事。从最外层分析: void(*fb)(int),这是一个函数指针,fb=signal(int sig_num,void(*handler(int)))。这是一个函数,只不过这个函数一个参数是int,一个参数是函数指针。
两个这么一结合,发现fb是函数,这个函数返回值是一个函数指针,而这个函数指针指向的函数返回值是void 参数是int。只不过这些写难以理解,但是利用typedef将这个函数指针“封装”起来就很好理解了。
typedef void(*func_p)(int);
上面是将func_p声明为 void ()(int)这样函数结构的函数指针。创造了一种新的指针类型,那么signal函数就可以简化成:
func_p signal(int sig_num,func_p p);
这么一写,就跟我们平常使用的函数结构一样了,好理解多了。
注意定义函数指针的写法: void (*funcP)(void)。指向void ()(int)函数的,这与基本数据类型指针不同:int* ip;
至于函数返回值又是函数指针的情况,那样的写法了解一下就行,一般用typedef简化。至于调用函数指针指向函数的方式就调用函数的写法一样。
//自定义func_p为新的指针类型
typedef void (*func_p)(int); void callback(int x)
{
printf("callback:%d\r\n",x);
}
//普通函数返回值是指针
int* function(int* p)
{
int* q;
q = (int*)malloc(sizeof(int)*);
*q = *p;
return q;
}
//函数返回值是函数指针,函数体的参数是普通指针
void (*function1(int* p))(int)
{
printf("p:%d\r\n",*p);
return callback;
}
//函数返回值是函数指针,而函数形参也有函数指针,注意函数指针作为函数形参的写法
void (*function3(int*p,void(*handler)(int)))(int)
{
void (*func_temp)(int);//函数指针的写法,与形参handler写法是一样的。
func_temp = handler;
printf("p:%d\r\n",*p);
return handler;//函数的返回值是函数指针,这里形参的函数指针类型与返回值函数指针的类型是一样的都是void ()(int)
}
//利用typedef定义的新指针类型重写的函数,更好理解。
func_p function2(int* p)
{
printf("p:%d\r\n",*p);
return callback;
}
验证:
int main(int argc, char *argv[]) {
int a = ;
int* iq;
void (*funcp)(int);
void (*funcp2)(int) = callback2;//定义函数指针并赋值,直接赋函数名
funcp2();
iq = function(&a);//函数值是指针,注意这里返回的指针是函数中在堆空间申请的空间,如果不free是不会被收回的。
//而函数体中定义的零时指针是函数栈空间。当函数体结束会被收回。因此返回的是无效地址。 funcp = function3(&a,callback2);//调用函数返回值跟参数都是函数指针的函数。function3有一个普通指针参数。
//将函数callback2传入,这个函数会被返回给funcp。这个时候函数指针指向的函数体是callback2
funcp(); //执行指向的函数体
printf("ret:%d\r\n",*iq);
system("pause");
return ;
}
执行结果: