数组、指针、数组指针和指针数组怎样理解
本文由 babystep原创,禁止转载!
本文通过语言加代码的方式,力图完全理解指针、数组、指针数组和数组指针这四个东西,尤其是指针数组和数组指针,每次用起来都得重新搜索是啥意思,所以这次决定用一篇博客说明白。
数组和指针经常用,但是理解时候容易有偏差,导致不能理解指针数组和数组指针的区别,所以建议读者一步一步详细阅读。对数组和指针有好的理解,可以直接调到指针数组和数组指针部分。
数组: 内存空间中一段连续的内存。例如 int a[5]; a是一段连续5个int大小内存片段的首地址,首地址这点很关键,关键在哪里?关键在这说明a是常量,而不是变量。所以,虽然a是地址,但它就是那5个int片段的首地址,你可以改变这个首地址中存放的东西,但是不能改变这个地址,也就是说不能改变a。如下做法是错误的:
int *p;
int a[5];
a = p; //错误,a是常量
指针: 是一个变量,这个变量的内容是一个地址,这个地址指向其他地方。什么是指向呢?指向的意思就是指针变量所保存的其他地址单元中所存放的数据类型。例如 int *p; p本身就是一个地址,32位系统下是4个字节,64位系统下是8个字节。它指向的数据类型用前面的int来说明,所以我们称p指向int数据类型。
指针变量是变量,所以可以给指针变量赋值,如下:
int *p;
int a[5];
p = a;//正确
说明数组指针和指针数组之前,先回顾下上面。
//请问下面语句对吗?为什么
char s[]="hello";
char *p = "wolrd";
s = p;
首先char s[] = "hello";
是对的,这是c语言中数组变量的典型初始化方法。但是char *p = "world"
为什么也可以?这是因为”world“常量字符串实际上是一个常量指针,指针指向的地方是字符串首字符。因此自然可以赋值给p。
第三句错误,上文已经讲了,s是数组变量,数组的首地址,而不是指针变量,所以是常量,不能给赋值。
接下来说明指针数组和数组指针
顾名思义,指针数组是数组,只不过数组的元素是指针;数组指针是指针,只不过指向的对象是数组。
//请问下面p是是数组指针还是指针数组
int (*p)[5];
//答案是 数组指针。这是因为'*'的优先级小于[],只能用括号来增加优先级,所以括起来的p首先与*
//结合,被认为是指针,指向一维数组,大小为5个int。
int a[5];
p = a;//错误,a是数组,p是数组指针
p = &a;//正确。
/*--------------------------------------------------------*/
//相对应的,指针数组如下,p先与[]结合,说明p是数组变量而不是指针变量
int *p[3];
int a[3][5];
p = a; //错误,数组变量是地址常量,不能赋值
p[0] = a[0];
由c语言知识知道,数组变量名是一个地址常量,这个地址常量表示的大小是随数组变化而变化的。举例来来理解:
int a[5]; //那么a就是&a[0]
//a+1实际是 &a[1]
int a[3][4];//稍微复杂点,a实际是a[0],a[0]是什么呢,是一维数组(矩阵的第一行)int [4]
//因此,a+1 就等于 a[1],是第二行一维数组的地址
理解了上面,定义
int a[3][4];
int b[3][4]={0};
//要用指针数组和数组指针表示二维数组a,该怎么做?
//指针数组做法:指针数组有三个元素,分别为三行的首地址
int *p[3];
for (int i=0;i<3;i++)
{
p[i]=a[i];
for(int j=0;j<4;j++)
p[i][j]=b[i][j]; //完成赋值
}
//数组指针做法:因为c语言约定最右边的下标为低维,即a[3][4]中4为低维,存储元素过程是从低维到
//高维,二维情况下是一行一行存储,所以需要知道列数
int (*p)[4];
p=a; //相当于p = a[0];
for(int i=0;i<3;i++)
{
for(int j=0;j<4;j++)
(*p)[j] = b[i][j];
p++; //因为是数组指针,所以每自加1,地址移动其数组大小的距离。
}
例子还是有点少,希望有点帮助吧。