理解数组指针、指针数组、函数指针、函数指针数组

(1) 指针数组 : 一个数组里放的都是指针,我们把他叫做指针数组:) 
int * a[10]; 由于它是一个数组,他是不能从堆空间里申请空间的。 
只能做个循环,每个元素去申请空间,或者每个元素去指向另外的地址空间。     
( 2 ) 数组指针 : 一个指向一唯或者多唯数组的指针; 
int * b=new int[10]; 指向一唯数组的指针b ; 
a 指向了一个栈空间中10个并排放置的 int 型元素的首地址 
int (*b2)[10]=new int[10][10]; 注意,这里的b2指向了一个二唯int型数组的首地址. 
注意,这里的b2的类型是int (*) ,这样表示一个指向二唯数组的指针。再注意,如果这样在堆空间里已经申请了内存,在释放内存的时候要保证每个空间都要释放。 
int (**b3)[2]=new (int(*)[2])[2]; b3表示一个指向(指向二唯数组的指针)的指针,我们在给他申请空间的时候一定要注意它的类型:它是int (*)型的指针,那申请空间的时候的类型为int(*)[元素个数],由于它后边还带个二唯数组每元的个数后缀,所以加上这个后缀就OK了。 
int (**b4)[2];表示每一个元素都指向(指向二唯数组的指针)的数组。 
由于它是数组,所以要是在堆里申请内存,就必须为每一个元素单独申请。 
b4[0]=new (int(*)[2])[2];原理同上 

(3) 指向了一个(指向指针的指针) 
    int ** cc=new (int*)[10]; 
        这种声明很简单因为cc的类型是int*型的指针,所以你要在堆里申请的话就要用(int *)来申请; 
(4) 多唯指针数组的指针数组。 
   int ** d[2];表示一个指向指针的指针数组;数组里有两个元素,每一个元素都是一个指针,这个指针指向另一个指针:) 
   再怎么变也是数组呀,呵呵, 
   如果你读懂了上边的,那下边的声明就很简单了: 
   d[0]=new (int *)[10]; 
   d[1]=new (int * )[10]; 


总结 : 只要知道了其中的指针类型,声明一个指针就很简单了,堆里申请稍微复杂点,不过知道了类型,也就稍微烦琐一点。 
  (1)int*ptr;//指针所指向的类型是int 

  (2)char*ptr;//指针所指向的的类型是char 

  (3)int**ptr;//指针所指向的的类型是int* 


  (4)int(*ptr)[3];//指针所指向的的类型是int()[3] 

       指针数组——每个元素都是指针的数组;
数组指针——指向数组的指针;


二 : 函数指针——指向函数的指针

关于函数指针,我想在我们可能需要写个函数,这个函数体内要调用另一个函数,可是由于项目的进度有限,我们不知道要调用什么样的函数,这个时候可能就需要一个函数指针

int a();这个一个函数的声明; 
ing (*b)();这是一个函数指针的声明; 
让我们来分析一下,左边圆括弧中的星号是函数指针声明的关键。另外两个元素是函数的返回类型(void)和由边圆括弧中的入口参数(本例中参数是空)。注意本例中还没有创建指针变量-只是声明了变量类型。目前可以用这个变量类型来创建类型定义名及用sizeof表达式获得函数指针的大小: 
unsigned psize = sizeof (int (*) ()); 获得函数指针的大小 
// 为函数指针声明类型定义 
typedef int (*PFUNC) (); 

PFUNC是一个函数指针,它指向的函数没有输入参数,返回int。


指针函数——返回指针的函数;


函数指针数组——每个元素都是指向函数的指针的数组。

三:回调函数

回调在C语言中是通过函数指针来实现的,通过将回调函数的地址传给被调函数从而实现回调。因此,要实现回调,必须首先定义函数指针,请看下面的例子:


void Func(char *s);// 函数原型
void (*pFunc) (char *);//函数指针

可以看出,函数的定义和函数指针的定义非常类似。

一般的化,为了简化函数指针类型的变量定义,提高程序的可读性,我们需要把函数指针类型自定义一下。


typedef void(*pcb)(char *);

回调函数可以象普通函数一样被程序调用,但是只有它被当作参数传递给被调函数时才能称作回调函数。

被调函数的例子:


void GetCallBack(pcb callback)
{
/*do something*/
}
用户在调用上面的函数时,需要自己实现一个pcb类型的回调函数:
void fCallback(char *s) 
{
/* do something */
} 
然后,就可以直接把fCallback当作一个变量传递给GetCallBack,
GetCallBack(fCallback);

如果赋了不同的值给该参数,那么调用者将调用不同地址的函数。赋值可以发生在运行时,这样使你能实现动态绑定。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值