指针和数组的区别

2012年01月10日 分类:学习笔记C++

一说到指针和数组,大多数人都认为两者是等价的,在大多数的情况下,指针和数组可以相互替换着用,但两者还是有很多不同的。

数组要么在静态存储区被创建(如全局数组),要么在栈上被创建。数组名对应着(而不是指向)一块内存,其地址与容量在生命期内保持不变,只有数组的内容可以改变。

指针可以随时指向任意类型的内存块,它的特征是“可变”,所以我们常用指针来操作动态内存。指针远比数组灵活,但也更危险,如果指针错误地指向的是一块没有使用的内存块,或者更严重的指向的是非数据的地址,就有可能引起毁灭性的结果。

理清两者的概念后我们先来看看两者的共同点。

#include <stdio.h>  
#include <stdlib.h>  

int main()  
{  
 int a[5] = {1,2,3,4,5}; 
 int *p=a;
 printf("%d\n",*p);
 printf("%d\n",*(p+1));
  
 return 0;  
}  

在这里指针p指向的是数组a中的第一项,也就是a[0],所以第一个printf输出的是1。由于数组开辟的内存是连续的,所以p+1指向的是数组的第二项a[1],最后的结果就是1 2 。

这里要注意p+1这个表达式,+1就相当于地址往后移动一段距离,至于具体移多少由指针的类型决定,比如这里是int型的指针,int在32位机器里是32位的,所以p+1就相当于往后移动32位的长度,这里对应了下一个数据的开头。

知道了这个后我们来看下一个例子。

#include <stdio.h>  
#include <stdlib.h>  

int main()  
{  
 int a[5] = {1,2,3,4,5}; 
 int *p = (int *)(&a+1);   
 printf("%d\n",*p);  
 printf("%d", *(p-1));  
  
 return 0;  
}  

大概很多人都会觉得输出是2 1 ,p指向的是a+1的位置,那就是2了,p-1当然应该指向1了。

但是结果却是: pointer p指向的是一段无用数据,而p-1指向的却是a的最后一项。 我们再回过去比较上面两段代码的不同之处,其中最大的不一样就是p的赋值了。在第二段代码中的&a是什么意思,a是一个长度为5的数组,对他取地址后会变成什么类型,这是解释上面问题的关键。

数组除了他存储的是静态连续的数据,这点和指针不同外,他还有一个属性————长度。当我们定义一个数组时他的长度就会固定下来,如果通过下标寻址超出了他的长度范围,编译器将出错。而指针没有长度的概念,只要不超出计算机内存的范围都可以用指针寻址,这也是指针的方便之处,同时也是最危险的地方,毕竟内存中有很多东西是不能被访问的。

&a的类型并不是int*,而是int*[5],&a+1指向的也并不是a的第二项,而是a[4]的下一项,显然他已经超出了a的范围。

注意到(&a+1)前面的强制转换符(int *),如果去掉的话编译器将报错,这也说明了(&a+1)的类型并不是int*,必须强制转换。

最后再总结一下,数组是静态的(内容可变,地址不变),而且是有长度的。

作者:wuyuan 本文来自Wuyuan's Blog 转载请注明,谢谢! 文章地址: https://wuyuans.com/2012/01/difference-pointer-and-array