现在的位置: 首页 > 综合 > 正文

再‘论’指针&数组

2012年05月16日 ⁄ 综合 ⁄ 共 1571字 ⁄ 字号 评论关闭

刚刚接到的通知,下周要去MS面试了。作为一个真心对C++不感冒的人来说,不知道要和他们聊什么了,没准还是HTML 5呢!今天和大家分享一个小知识,关于C的数组和指针的一点学习。

     我曾经迷恋上了《C专家编程》,断断续续的看了不到一个月,有一章叫做再论数组,突然想起了,里面曾经谈到的一个经典的话题,就是数组和指针转换的问题。

     我们首先定义一个数组,(数组就是开辟一段连续的内存保存数据)

      char a[10] = "abcde";

     补充一点背景知识:a保存的是数组的第一个元素a[0]的地址。 (关于这里根据很多朋友反馈,补充了一下http://www.cnblogs.com/octobershiner/archive/2012/04/17/2453320.html

     我们知道我们可以通过a[n]来直接访问某一个位置的元素,同时也可以用指针来操作

     char *p = a;


 

     这时候,我们可以使用*(p+n)来实现同样的效果,当然也可以p[n]来操作,这个时候就有了一个说法,指针和数组是“一样的”,真的一样吗?

     但如果我们仔细思考C语言编译器的内存分配的时候,就会发现,指针操作实际上多了一步的操作:

         

     从图中可以看出,p保存的是一个地址,其实*p得到的是一个地址,*P表示地址中的内容,也就是a的地址,这个地址就是数组a的首地址。所以当我们通过指针操作元素的时候,首先是从指针中获得一个地址x,然后编译器再去访问x地址,而用数组操作元素的话,则直接访问本地址的内容。 这是一个区别。

     这个区别在什么时候可以出现,就是在定义和声明的时候,如果你定义了一个数组,而在另一个文件中用extern关键字声明成了指针就会出错。因为二者在内存上的分布是不同的。

     另一个经典的区别是,p是一个变量,可以对其本身进行改变,但是数组名是一个常量,只读不可写。


 

     为什么数组可以用指针偏移量来做呢?其实是下标引用也将会被编译器改为用指针偏移量来执行,原因是在底层硬件上,指针偏移更加的高效和容易实现。

     Peter 曾经写到多年来对于指针和数组可以相互转换的误区,就是大家一直没有看到完整的说法,指针和数组等价的前提是做函数参数的时候。。原因是无论函数参数是数组还是指针,最终编译器都会将其转化为指针。

     我按照老人家的要求写了一个demo,就是用来演示这一事实。          

         

     上面的两个方法用于返回参数的大小,我们将比较一个数组传入函数后,其大小是否还是原来的数组

       

       上面的两个函数,将分别打印参数的地址,我们将验证所谓的首地址还是不是数组的首地址  

      

      主程序,我们定义了一个全局的数组,并且打印了他的大小,可以预测数组的size是6.下面我们看一下程序的执行结果

       

      

      可以看出,原来数组的size是6,但是传入函数后,无论是以数组和指针的形式,大小都变成了4,没错就是一个指针所占的大小,而不再是6哥字符的空间了,说明了什么?

      没错,数组都被转换成了指针!

      接下来我们打印函数参数的地址,发现其地址并不是数组元素的首地址,根据我们的第一个图,内存分布,我想大家也可以看懂,现在的参数已经不是数组名了,而是一个新的指针。


 

     那么,编译器为什么这么做呢?就是因为传参的时候,如果我们传进一个整个的数组,效率会大大降低,转换成指针可以节省时间和空间。

      其实,总结一下,数组和指针也没有那么纠结,其实就是操作内存的不同形式,明白了内存的操作,以上的东西就都是形式上的东西了~

      

     本文完整源代码:https://github.com/octobershiner/Algorithm/tree/master/Pointer_Array

 

 

 

抱歉!评论已关闭.