指针与数组知识点总结

来源:互联网 发布:淘宝延长发货时间 编辑:程序博客网 时间:2024/06/05 15:47

本文基于flying_music博客,加入自己的一些理解,请周知


1.印子——指针为什么需要返回类型

   

  我们用C语言写了这样的语句

[cpp] view plain copy
  1. int a;  
  2. a = 3;  
编译器为了完成这两句代码,首先在编译过程中要创建一个符号表,样子大概如下图:

   然后在运行过程中,编译器发现a=3这句代码时,会在符号表里找a对应的地址,然后把3放入对应的地址,即这里的0x1000。(A找B盖章,直接盖到了)

   如果是*p=3会怎么做呢?首先,符号表变成了这个样子

    

    

   在运行过程中,编译器遇到*p=3时,首先要从符号表中找到p的地址0x1004,然后取出0x1004中的内容,这里假设为0x2000,最后把3放到0x2000内存地址中,即*(0x1004)=3。

   相比于利用普通变量,利用指针存取数据的过程中多了一部取地址的的过程。这也就是指针变量与普通变量最大的不同。

   再来看一下指针加偏移量的引用方式,还以上面的指针p为例,让我们来看一下*(p+2)=3的实现过程。

   首先,编译器从符号表中找到p然后,取出里面的内容0x2000,再根据其类型(int*),做一个运算,      

   0x2000+2×sizeof(int)=0x2008。所以编译器会把3放入0x2008这个内存地址。

   整个过程可表示为*(*(0x1004)+2)=3。(A找B盖章,B讲你去C部门,找那谁盖章(偏移))

   从这里也可以看出为什么指针必须有类型,因为在引用过程中要用到指针所指类型的长度。

来看一下,数组元素的引用是如何实现的,假设我们定义了一个数组,并对其元素进行了引用

[cpp] view plain copy
  1. int b[10];  
  2. b[4] = 3;  
对应的符号表变成了这个样子


    那b[4]=3如何完成呢?首先,找到符号b,然后发现其类型为int[](假想表达方式,C语言中不支持这样写),所以计算式变成了0x1008+4×sizeof(int)=0x1018,然后把3放入0x1018就可以了。用一个式子表达就是*(0x1008+4)=3。(A找B盖章,B讲你去我们部门,找那谁盖章(偏移))

    从上面的寻址式子可以看出,普通变量、指针、数组三者对于编译器的区别。具体到数组,它即具有普通变量的直接性,即不用取两次地址里的内容而是取一次,同时又具有和指针相同的偏移量引用方式,即下标的实现实际是由指针加偏移量实现的。

    为了表明上述事实(或者是为了提高C语言入门门槛),C语言对指针与数组的引用方式做了可以“交叉”使用的语法规定。就上面的例子来说,如果p指针指向数组b时,b[i]、*(b+i)、p[i]、*(p+i)都是对数组第i个元素的正确引用方式,这也给很多C语言学习者制造了“指针和数组一样”的错觉。

    

2.在函数形参中的表现

在向函数传递参数时,如果实参是一个一维数组,那用于接受的形参为对应的指针。也就是传递过去是数组的首地址而不是整个数组。这么做的原因主要是效率,这是无可争议的,但为了使用上的简便与通用,C语言接受两种形参的写法,即下面两种写法是相同的

[cpp] view plain copy
  1. int foo(int *a, int n);  
  2. int foo(int a[], int n);  
甚至是

[cpp] view plain copy
  1. int foo(int a[20], int n);  
    在底层都是完全一样的形式。这简化了C语言的使用,但同时也增加了对其进一步理解的难度。

    至于哪种写法好的争论,只要理解了,用哪种写法倒是不必强求。

    指针形式表明了传参过程的实质,而数组形式表明了这个指针对应一个数组实参,甚至后面的数字可以提供数组长度的参考。

3.如何区分二者

数组和指针的关系如此微妙,那如何区分呢?

    首先说为什么要区分,主要由两个方面的原因

    一是C语言的主要战场还是偏向于底层的,使用者对这块儿一定要搞清楚,比如编译器,硬件系统等相关知识。       二是在特定的情况下,二者的表现的确不同,最常见的就是sizeof关键字的作用结果,另外还有取址操作符&的结果等情况。

   至于如何区分,个人认为凡是要区分两个相关的概念,一定要将二者的作用区分清楚,即为什么要有这个东西。

   数组和指针也是一样,指针是一类特殊的变量,主要用途是函数间的传址,用这种方式来改变实参内容。

   而数组是用来实现线性表的结构,用于把同类对象集中在一起放置。

   所以,如果下次有人问你数组和指针的区别,你首先第一句要说的就是二者根本没有联系,这么说并这么理解,对于弄清这两个家伙的关系是很有裨益的。