c/c++ 的数组

  数组可以想象成一个对象,其中数组名指向对象的首地址,当用sizeof计算数组名时,得到的是数组这个对象占用的内存大小,数组名称的加减和[]操作都不同于一般的指针,而且,数组每一个元素的内存地址是连续的(这里的数组都以二维数组为例,而且说的是静态数组),例如第一行的最后一个元素的和第二行首元素地址是连续的。

  函数形参如果是多维数组,二维及以上的大小要给出,例如 int a[][4],因为在函数内部,编译器需要知道a+1要跳多远,只有知道了每一行有多少个元素才行。

  把数组名赋值给指针,(不管是赋值给什么样的指针),指针都不会获得数组名所拥有的特性,sizeof作用于指针得到4,虽然指针可以用[][]获取元素,但是无从得知指针指向的数组的这块内存的大小,这也就是为什么给函数传递数组作为参数时,要增加一个参数传入数组的大小。

  上面提到的数组指的都是静态数组。

  动态数组是这样的,例如

int **a;
a = new int*[10]; 
for(int i=0;i<10;i++)
     a[0] = new int[10];

很明显,动态数组每一行之间的内存地址没有连续性,因为都是单独申请的。而且sizeof作用于指针a得到4。

void arr(int **a) //有必要增加参数,传入行列数
           
{
           
cout<<sizeof(a)<<endl; // 4
           
//这里的a完全失去了数组的任何特性,要访问数组的元素,只能用以下方法
           
//然后针对传入的是动态数组还是静态数组,处理方法又有所不同
           
//if 静态数组
           
//先将a转换成int *类型,也就是a成为指向原数组首元素的指针
           
//要访问第i行第j列, *((int*)a+col*i+j )
           
//if 动态数组
           
//要访问第i行第j列, a[i][j],因为动态数组本身就是int **
           
}

  从上面的例子得出结论,传数组进函数,如果是静态数组,最好不要用**,而是用 [][],这样在函数内部才能保留用[][]访问数组元素的能力。但要记住,只要传进函数,sizeof就只能得到4了,所以必须传入数组的相关信息,如行列数,否则没法防止越界访问。

  一点想法,静态数组,就像对象,加减、*和[]操作都在内部有相应的操作,和动态数组不同的是,静态数组并没有为每一行分配一个指针变量存放行首地址,但是,静态数组却能像动态数组那样通过[1]直接获取第二行的行首地址,这就是静态数组这个对象内部做了运算,可以这么看,这个对象里面有3个成员变量,第一,数组首元素地址(就像对象的地址那样),第二,行数,第三,列数。例如,计算数组大小就用到了行列数,取下一行首元素地址就用到了行列数。

posted @ 2013-02-19 23:35  wongzawing  阅读(107)  评论(0编辑  收藏  举报