C语言中指针与数组之异同

前段时间面试的时候有一个问题涉及到了数组与指针的区别,发现自己在潜意识中把数组名和指针等同起来了。而事实上数组与指针确实是不同的,被问及二者区别的时候,我就只能含糊地说数组含有长度信息云云。 

于是自己认真研究,思考了这个问题。后来发现《C专家编程》中原来有一章就是《令人震惊的事实:数组和指针并不相同》。

 为什么我们会混淆数组与指针呢?虽然它们是不一样的概念,但使用起来是在是太像了,我们通常用数组的方式去访问一个指针指向的区域,同样也可以用指针的方式来访问一个数组,如下所示:

char * p  = "test";  // 声明一个指向字符串的指针p
char a[5] = "test";  // 声明一个字符数组a
p[2] = 'a';          // 用数组的方式来访问指针指向的字符串
*(a+2) = 'a';        // 用数值的方式来访问数组

那么我们用数组名(上面的a)和指针(上面的p)来访问数据的时候,区别是什么呢?可以用以下的两幅图来说明:  

                                                        图1 数组与指针的访问  

上面的图清晰地展示了访问一个数组的元素和访问一个指针指向的区域的区别。在声明语句中,a和p均是左值,这意味着它们的值是在编译期确定的,编译之后a和p分别对应着内存中的一个地址(上图中用1000,2000,3000等来描述地址),这里我们可以看出它们之间微妙的差别,数组名a直接就是数组存储区域开始处的地址,而指针p所存储的值才是指针所指内存区域开始处的位置(p本身的值是它所在内存区域的地址)。也就是说a与p的差别是地址与指针的差别,而这两个概念同样也d有点令人迷惑,这里再理清一下。所谓的地址,是用来标明内存中的一个位置,而指针,则是一个用来存储地址的变量。一个整型的变量和一个整数是不同的东西(整型的变量用来存储整数的值),地址与指针也是同样的道理。由此我们也就能够理解为什么在C语言中经常会声明一个指针来引用一个数组,要向函数传递一个数组的时候,参数的类型也往往定义成一个指针,而反向操作是不可能的。至于是用下标还是用加上偏移量再解引用的方式来访问,两者是等效的,事实上编译器往往把后者前者转换成后者来处理,它们实质上都是以某地址为基准取一定的偏移量处的值。

 在单纯的使用层面上,我们操作一个数组和操作一个指针几乎是完全一样的,就像我们需要一个数值的时候既可以用一个变量也可以用一个魔数。虽然数组与指针在许多其它方面也存在一些差别,比如对它们进行sizeof操作的时候就会有不一样的结果(指针是指针的长度,而数组是其包含元素的个数),但我觉得以上的讨论是数组与指针之间根本性的区别,具体的一些差异都是由此引起的,我们依旧能够把数组名当作是一个指针来操作,但记住它们其实并不相同。

你可能感兴趣的:(数组,指针,C\C++)