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 ",x); } //普通函数返回值是指针 int* function(int* p) { int* q; q = (int*)malloc(sizeof(int)*10); *q = *p; return q; } //函数返回值是函数指针,函数体的参数是普通指针 void (*function1(int* p))(int) { printf("p:%d ",*p); return callback; } //函数返回值是函数指针,而函数形参也有函数指针,注意函数指针作为函数形参的写法 void (*function3(int*p,void(*handler)(int)))(int) { void (*func_temp)(int);//函数指针的写法,与形参handler写法是一样的。 func_temp = handler; printf("p:%d ",*p); return handler;//函数的返回值是函数指针,这里形参的函数指针类型与返回值函数指针的类型是一样的都是void ()(int) } //利用typedef定义的新指针类型重写的函数,更好理解。 func_p function2(int* p) { printf("p:%d ",*p); return callback; }
验证:
int main(int argc, char *argv[]) { int a = 100; int* iq; void (*funcp)(int); void (*funcp2)(int) = callback2;//定义函数指针并赋值,直接赋函数名 funcp2(1001); iq = function(&a);//函数值是指针,注意这里返回的指针是函数中在堆空间申请的空间,如果不free是不会被收回的。 //而函数体中定义的零时指针是函数栈空间。当函数体结束会被收回。因此返回的是无效地址。 funcp = function3(&a,callback2);//调用函数返回值跟参数都是函数指针的函数。function3有一个普通指针参数。 //将函数callback2传入,这个函数会被返回给funcp。这个时候函数指针指向的函数体是callback2 funcp(1000); //执行指向的函数体 printf("ret:%d ",*iq); system("pause"); return 0; }
执行结果: