浅谈 指针数组&数组指针 指针函数 函数指针

    很多人都说指针是C语言的精华,指针可以与数组、函数结合起来,形成指针数组,数组指针,指针函数,函数指针。可以看出,这四个名词两两对应,只是前后换了顺序而已,但是在本质上是有区别的。下面一起来研究一下它们。

    首先,我们对指针和数组之间的关系进行研究。我们先理解,对于一个一维数组来说,我们可以定义一个一级指针来保存其数组名内的值,这是没有问题的。那么,如果有一个二维数组,我们定义一个二级指针来保存其数组名内的值,这是不行的,原因是二者的类型是不一致的。那么该怎么做呢?我们一步一步来,先看以下代码及其运行结果:

     

         这就出现了数组的三值合一这一概念,主函数中的第二行是对数组名的内容进行访问,但数组名保存的是其首元素的地址,于是我们得到第一个地址,而第三行是明确对数组首元素取地址,第三个也是在取地址,但是是对整个数组取地址,可以看到这三个值是一样的。根据上面说的指针可以用来存放地址,那么我们是不是可以定义三个指针来分别保存这三个地址呢?请看下图:

        

     是不是可以看到,前两个是可以的,但是第三个数组名的地址是不能用用指针来存放的。为什么前两个可以呢?ar可以是因为它保存的首元素的地址,首元素是一个整型,整型的地址当然可以用指针来接收;&ar[0]明显是对首元素取地址,首元素是整型,整型地址可以用指针接收;但是对&ar来说就不一样的,它是对整个数组取地址。请看,如果我们定义一个整型,想要接收它的地址就要定义一个整型指针来接收,那么就可以推出,既然&ar是整个数组的地址,是不是要定义一个指向数组的指针来接收?那么,要如何定义呢?只需要将上面的最后一行代码改成:int (*p2)[10]  = &ar; 就可以了。

       好了,说到这儿我们今天的第一个名词出现了:即数组指针,即指向数组的指针的简称。所以到这儿你应该明白,如果要接收整个数组的地址就要定义一个指向数组的指针来接收,并且保证该数组的大小与要取地址的数大小一致。接下来让我们回过头来看二维数组,对于二维数组来说,定义二级指针并不能保存二维数组的数组名,我们又该如何定义呢?这得认真分析了。

       很重要的一点需要谨记,数组名永远代表整个数组空间,其次,数组名内部有值,值是首元素的地址,那就意味着,要想接收数组名,那就要接收数组名保存的值,它的值是首元素的地址,对于一维数组,首元素是整型,定义一个整型指针就可以接收,对于二维数组来说,我们就必须要了解其首元素到底是什么?我们知道,二维数组是数组的数组,它的首元素是一行,而这一行也是一个数组,即其首元素是一个数组,那么我们该如何定义呢?请看下面:

        

      这样就可以啦。到这里我们就可以来区别数组指针,指针数组这两个概念了。那么如何记忆呢?当你听到这两个概念的时候,你要用心注意后两个字,如果是数组指针,那么强调的是指针,只不过是指向数组的指针;若是指针数组,那毫无疑问强调的是数组。请往下看:

       

       请仔细看,是不是发现上面的数组指针与指针数组只是相差了一个 ( ) 而已,而名字却不同。这是因为 * 和 [ ] 的结合级别不同造成的, [ ] 的结合级别高于 * ,在没有( )时,标识符会先和 [ ] 结合形成数组,然后再会和 * 结合,所以大前提就是数组,只不过它保存的类型是整型的指针类型,就称为指针数组;如果有 ( ) ,那么 标识符先和 * 形成指针, 出了 ( ) 遇到的是数组,就说明指针指向一个数组,那么称之为数组指针。

      既然指针可以指向数组,就可以指向函数咯,接下来我们一起来区分指针函数和函数指针。一样的道理,还是看最后两个字。注意: 要定义一个指针指向一个函数,要做到以下几点相同:1. 返回值相同  2. 参数个数相同 3. 对应参数的类型要相同。 请看以下代码:

        

        要注意一点,数组指针可以进行 ++ 、- -的,函数指针是不允许的。请看代码:

        

         下来谈谈指针数组作为函数的返回参数,我们经常这样写主函数 void/int main() ,对吧,这个函数其实是有参数的,即 int/void main (int argc, char *argv[ ]), 其中argc代表参数个数,argv代表参数值,它是字符指针的指针数组。

VS2010里在菜单栏->项目->BlogTest属性->配置属性->调试->命令参数 中输入值,比如输入xx, yy, zz,中间用空格隔开,然后将参数个数与值打印出来,请看下面的代码:

        

       是不是发现只传进3个值,但是输出结果却有4个,实际上当我们不传参数时,主程序也有1个参数,这个参数是本应用程序的路径,即你所创建的可执行程序的路径。那么为什么主函数里有这种类型的参数呢?因为在可执行程序里,我们不知道用户传进的参数有多少字符,为了解决这种不定长的问题,我们把不定长问题转化为定长问题,可以定义一个数组来存放字符串的首地址,这样的话,如果你有6个参数,即6个字符串,我们把每个字符串首元素的地址保存,就相当于指针指向了该字符串,至于字符串有多长就不用关心了。而且,在win32下每个字符串都是4个字节(因为是指针类型的),这就让用户可以传入任意大小的参数了。

        到这里,今天的内容就结束了,感觉与指针相关的东西都不容易理解,但是要想学好C语言,指针就必须的理解透彻,希望我的博文能给和我学习同样内容的你有所帮助,如若有错,请指出,谢谢!



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值