函数指针复杂的例子

函数指针声明必须包含正确的返回值类型和输入类型
如函数原型:
int pam(int );
正确的函数指针应该为:
int (*p)(int);
如果写为
double (*p)(int);肯定是错误的。


当然这里指的是简单的函数
如果函数更加复杂如下:
const int *f1(const double *,int)
首先这个函数原型是一个返回一个const int 指针的函数,其次
他需要接受2个参数一个是const double类型的指针,当数组作为
形参的时候传递的实际上是地址而不是实际的数据,第二参数就是
一个整形。
那么关于这样的函数我们怎么声明一个函数指针呢?如下:
const int* (*p)(const double *,int)
首先这是一个指针p并且为一个函数指针他带入两个形参,其次
他的返回值为一个指针这个指针是const int类型的。
如果要建立一个数组,其中包含3个这样的函数指针该如何呢?
const int* (*p[3])(const double *,int)
类似的我们经常使用*argv[4],他就是一个包含3个指针的数组
只是这种指针是函数指针。
我们知道数组的名字就是数组内存空间的首地址,那么。这里
p就是这样一个指针,他是指向函数指针的指针,当然是第一个
p+1呢当然也是也是一个指向函数指针的指针,当然是第二个元素。
当然如果调用我们可以
const int *a = (*p[1])(darray,10)
或者
const int *a = p[1](darray,10)
这两者来自不同的认为,一个认为p[1]既然是一个函数地址那么要
取其函数就是*p[1],另外一个认为p[1]为函数的地址而函数名字本生
就是地址,那么这麽调用也没有问题,如此C/C++折中后认为他们都
正确,个人认为(*p[1])(darray,10)更加明了
如果直接取值即可以
const int a = *((*p[1])(darray,10))
或者
const int a = *(p[1](darray,10))


更加复杂一些


const int* (*(*pt)[3])(const double *,int) = &p;
首先pt是一个指针,然后合[]进行结合,说明他有3个元素的数组
而这个素组包含的3个元素是**pt的类型,并且他是函数指针,
最后这个pt指针指向了&p


const int* (*p[3])(const double *,int)
首先p是一个指针,并且是指向数组的第一个元素,并且数组中每一个元素都是
函数指针。
那么&p就是一个指向 函数指针的指针 的指针,听起来很复杂。确实也比较复杂。
那么
const int* (*(*pt)[3])(const double *,int)
也是一个指向 函数指针的指针 的指针。
调用为
const int *a = (*(*pt)[1])(darray,10)
或者
const int *a = (*pt)[1](darray,10)


const int a = *((*(*pt)[1])(darray,10))
或者 
const int a =*((*pt)[1](darray,10))




如同二维素组的指针
int (*p)[3] [3]代表了有3个元素,及(*p)[0],(*p)[1],(*p)[2],当然他也等价
为*p+0,*p+1,*p+2的3个元素地址,第二行为*(p+1)+0,*(p+1)+1,*(p+1)+2
(*(p+1))[0],(*(p+1))[1],(*(p+1))[2]
这里形式和我们这里的形式
const int* (*(*pt)[3])(const double *,int) = &p;
有点相识,
那么引申开来,&p或者pt就是整个函数指针素组的地址,他包含了3个元素,

(*pt)[0]或者*pt+0
他就是一个函数指针形参为(const double *,int)
这里注意下虽然p和&p有同样的地址,但是他们步长并不一样。


接下来看一下相对比较复杂的函数指针的列子


<ptad<<endl; pointer="" to="" function="" array="" address<pt+0<<endl;  ="" pointer="" to="" function="" array="" number="" 1<pt+1<<endl;  ="" pointer="" to="" function="" array="" number="" 2<datac<<endl;
<step;i++)
<endl;
<step;i++)
<endl;
<count<<endl;
<step;i++)
<endl;
<endl;
<count<<endl; 
  1 /*************************************************************************
  2   > File Name: functionp.cpp
  3   > Author: gaopeng
  4   > Mail: gaopp_200217@163.com 
  5   > Created Time: Thu 26 May 2016 05:42:20 PM CST
  6  ************************************************************************/
  7 
  8 #include
  9 #include
 10 using namespace std;
 11 
 12 const int* add(const int *data,int step);
 13 const int* mul(const int *data,int step);
 14 
 15 int getdata (int *data,int step);
 16 
 17 
 18 
 19 int main(void)
 20 {
 21     int datac=0;
 22     int data[5];
 23     const int* (*pt[2])(const int *,int);      //pt[2] is function pointer array have 2 number
 24     const int* (*(*ptad)[2])(const int *,int); //ptad is function array adress step is 2 
 25     getdata(data,5);
 26     pt[0]=add;                                 //function pointer 
 27     pt[1]=mul;                                 //function pointer 
 28     ptad=&pt;
 29     cout<<"function array address is "<<ptad<<endl; //pointer to function pointer array address
 30     cout<<"function 1 address is "<<pt+0<<endl;     //pointer to function pointer array number 1
 31     cout<<"function 2 address is "<<pt+1<<endl;     //pointer to function pointer array number 2
 32     for(int i=0;i<2;i++)
 33     {
 34 
 35         datac += *((*(*ptad+i))(data,5)); //*ptad+i is pointer to add address and mul adress,*(*ptad+i) is add and mul 
 36     }
 37     cout<<" mul+add "<<datac<<endl;
 38 }
 39 
 40 
 41 int getdata (int *data,int step)
 42 {
 43 
 44     for(int i=0;i<step;i++)
 45     {
 46         if(!(cin >> data[i]))
 47         {
 48 
 49             cin.clear();
 50             while(cin.get()!= '\n')
 51             {
 52                 continue;
 53             }
 54             cout<< "please input int data"<<endl;
 55             exit(1);
 56         }
 57     }
 58     return 0;
 59 }
 60 
 61 
 62 const int* add(const int *data,int step)
 63 {
 64 
 65     static int count=0;
 66     for(int i=0;i<step;i++)
 67     {
 68         //cout <<"add:" <<*(data+i) <<endl;
 69         count += *(data+i);
 70         //cout<<count<<endl;
 71     }
 72     return &count;
 73 }
 74 
 75 const int* mul(const int *data,int step)
 76 {
 77 
 78     static int count=1;
 79     for(int i=0;i<step;i++)
 80     {
 81 
 82         if(*(data+i) == 0)
 83         {
 84 
 85             cout<<"Cannot data into 0"<<endl;
 86             exit(0);
 87         }
 88 
 89         //cout <<"mul:"<< *(data+i) <<endl;
 90         count *= *(data+i);
 91         //cout<<count<<endl; 
 92     }
 93     return &count;
 94 }

 其实整个例子很简单,就是计算几个输入值的和与乘的和,但是为了展示
 const int* (*(*ptad)[2])(const int *,int);
 这样一种ptad指向一个 函数指针数组的指针,所以这样写了。
 实际数组的名字也是指针那么我们可以理解为
 ptad指向一个 指向指针的指针 的指针
 注意到结合性(*(*ptad)[2])(const int *,int)
 不要写成*(*ptad)[2](const int *,int)
 很明显()的结合性强于*
 那么(*ptad)[2]先与(const int *,int)结合在结合*
最后看看程序的输出
1
2
3
4
5
function array address is 0x7ffeede71e60
function 1 address is 0x7ffeede71e60
function 2 address is 0x7ffeede71e68
 mul+add 135

可以看到ptad和pt+0的地址一样但是他们的含义不同ptad的步长为2是函数指针数组的地址,而pt+0 是第一个函数的指针地址
 


</count<<endl; 
</endl;
</endl;
</step;i++)
</count<<endl;
</endl;
</step;i++)
</endl;
</step;i++)
</datac<<endl;
</pt+1<</pt+0<</ptad<
上一篇:docker容器-consul集群搭建


下一篇:彻底搞定C指针-函数名与函数指针【转】