那么什么时候数组&指针是相同的呢?
在c语言的标准中有如下说明:
1:表达式中的数组名被编译器当作一个指向该数组的第一个元素的指针。
2:下标总是于指针的偏移量相同。
3:在函数的声明中,数组名被编译器当作指向这个数组的第一个元素的指针。
对于第一点比如:
int a[10],*p,i=2;
有几种访问a[i]的方式,作用是一样的。
[1]:p=a;p[i];
[2]:p=a;*(p+i);
[3]:p=a+1;*p;
由此♂得出,对数组下标的引用总是可以写成“一个指向数组首地址的指针&偏
移量的和”
对于第三点的理由很简单,数组可能很大,如果作为形参也用传值的方式的话没
那么时间&空间上面来说是实在过不去的。
多维数组
♂知道一维数组的名字就是一个指针常量。那么多维数组也差不多。唯一的区别
就是,多位数组第一维实际上指向的是另外一个数组。
例如:
int max[3][4];
那么,max实际上是一个指向10个int元素的指针。
max+1就是指向max的下一行的10个元素。
*(max+1)也是一个指针,也许有点难理解,那么这么看吧.max[1]是什么?是一个
数组,那么这个数组名max【1】不就是一个指针么?数组名的值是个常量指针。
它指向数组的第一个元素。max[1]=*(max+1);
例子:
[img]http://images.blogcn.comude<iostream>
using namespace std;
int main()
{
int a[3][2]={1,1,3,5,4,7};
cout<<a<<" "<<*(a+1)<<" "<<&a<<" "<<a[0]<<endl;
system("pause");
}
可以看出上面的观点。*(a+1)仍然是一个指针,指向当前行的首元素。
那么自然,*(max+1)+5;就是指向当前行的第6个元素了。
现在*(*(max+1)+5)才是对int的解引用,访问了那个整型变量。
指向数组的指针
int vector[10],*vp=vector;//合法,指针指向数组首元素。
int vector[3][10],*vp=vector;//不合法,在这里,vp是一个指向整型的指针,
但是vector却是一个指向整型数组的指针,在这里类型不匹配。
正确的声明应该是
int (*vp)[10]=vector;//按照在《怎么读一个很长的声明中》说得,这个应该读
成:vp是一个指向有10个整型元素的指针。ok 类型匹配了。这个时候vp指向
vector的第一行。
也许这不能满足你的要求,你希望有一个指针能遍历这个数组的所有元素,而不
是现在只能一行一行的取值。
那么这两个可以满足:
int *p=&vector[0][0];
int *p=vector[0];
作为函参数的多维数组
上面说过了,数组作为函数参数是作为指针传递的。多维数组也是一样。但是区
别在于多维数组的每个元素本身是另外一个数组,编译器需要知道它的维数。
例如:
int vector[3][4];
这个二维数组传递给函数的时候要这么写。
void fun(int (*p)[4]);
or
void fun(int p[][4]);
其中第二维是必须的,因为编译器需要知道这个维长度才能对下标求值。
关于二维数组传参常犯的错误就是
void fun(int **p);
看出来了么?这个指针根本没有任何关于维数的声明,所以数错误的。
=======================================================================
上面第1和第3点错误,只要说到数组名是指针,全错。
“多位数组第一维实际上指向的是另外一个数组。”这句话也错,C实现的是数组的数组,不是多维数组,多维数组与数组的数组有本质的区别,多维数组根本就不是“第一维实际上指向的是另外一个数组”,这句话用在数组的数组上才是正确的。
=======================================================================
语言迫于本身的语言特性,没有实现多维数组,而是用数组的数组当作多维数组。由于数组的数组与多维数组的内存映象和使用方式都是相同的,使得许多C程序员对这两种数组的区别模糊不清。
数组的数组与多维数组的主要区别,就在于数组的数组各维之间的内在关系是一种鲜明的层级关系。对于数组int a[7][8][9],如果要访问元素a[4][5][6],它的地址就得这样获得:先通过*(a+4)求出第一维第5个数组的地址,然后计算第二维第6个数组的地址*(*(a+4)+5),最后才能得出a[4][5][6]元素的地址:*(*(a+4)+5)+6。这个过程是需要层层解析的。
而真正的多维数组并没有这么多“束缚”,由于各维之间不是层级关系,元素a[4][5][6]的偏移量可以这样直接获得:(4x8x9+5x9+6)xsizeof(int),再加上数组的首地址就是元素a[4][5][6]的地址了。
但是,c语言的数组能够这样用首地址加上(4x8x9+5x9+6)xsizeof(int)的形式来访问元素吗?显然是不行的。根本原因就在于C语言的地址不但有类型,还有层级关系。就是这种层级关系造成了C语言只能用数组的数组当作多维数组。如果C语言非得要实现真正的多维数组,那么地址与指针的概念就得重新改写了。
========================================================================
“但是,c语言的数组能够这样用首地址加上(4x8x9+5x9+6)xsizeof(int)的形式来访问元素吗?显然是不行的。”
为什么不可以呢?
我试了一下,在tc2.0下,a[4][5][6]的地址与&a[0][0][0]+(4x8x9+5x9+6)的值是一样