这篇小文介绍了关于指向二维数组指针的知识,来源于一道问题:http://topic.csdn.net/u/20110429/14/7fd61fd9-c1d4-4bee-aea9-6649bd3fd10f.html 先看看一下的代码,后面会有总结:
结果:
first :*( p[ i ]+j )
1 2 3 4 5 6 7 8 9
second : p[ i ][ j ]
1 2 3 4 5 6 7 8 9
thrid :*(*p+ i*3+j )
1 2 3 4 5 6 7 8 9
fourth :*(*(p+i)+j )
1 2 3 4 5 6 7 8 9
call plus_a( ):
2 4 6 8 10 12 14 16 18
从代码中我们可以看出,设已经定义一个二维数组aa,对于二维数组的访问除了可以使用通常的下标法:aa[ i ][ j ]以外,我们还可以采用一下方法:
(前提定义了:int aa[ 3 ][ 3 ];int*p)
1、将二维数组看成一维数组,即将 p=&aa[ 0 ][ 0 ],然后使用p++方式访问;
2、数组名aa代表整个数组的首地址,对于二维数组来讲aa[ i ]表示第i行的首地址,因此"aa[ i ]+j"是元素aa[ i ][ j ]的地址,并且aa[i]==*(aa+i),这样"aa[ i ]+j"又可以写成"*( aa+i )+j";
3、利用每行的地址,结合指针p来访问:
p=aa[ i ];
然后p++循环访问就可以了;
注意,有如下的等式:
&aa[ i ][ 0 ]=aa[ i ]=&aa[ i ]=aa+i=*( aa+i );
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
下面是网上的一些资料:
二维数组new小结
1.
A (*ga)[n] = new A [m][n]; //定义一个指向二维数组的指针数组的方法,必须指明第二维的长度
... //给出第二维长度的作用是可以知道指针ga的+1/-1的单位长度
delete []ga;
缺点:n必须是已知
优点:调用直观,连续储存,程序简洁(经过测试,析构函数能正确调用)
2. A** ga = new A* [m]; //定义一个指向指针数组的指针
for(int i = 0; i < m; i++)
ga[i] = new A[n]; //分别对指针数组的成员赋值
...
for(int i = 0; i < m; i++) //要进行两次析构
delete []ga[i];
delete []ga;
缺点:非连续储存,程序烦琐,ga为A**类型
优点:调用直观,n可以不是已知
3. A* ga = new A [m*n];
...
delete []ga;
缺点:调用不够直观
优点:连续储存,n可以不是已知
4. 2的改进版
A** ga = new A* [m];
ga[0] = new A [m*n]; //相当于1维数组
for(int i = 1; i < m; i++)
ga[i] = ga[i-1]+n;
delete [] ga;
优点:连续存储,n可以不是已知,析构方便,猜想只需delete [] ga;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
二维数组的初始化方式:
1、 int aa[ 3 ][ 3 ]={1,2,3,4,5,6,7,8,9}; //全部初始化
2、int aa[ 3 ][ 3 ]={ {1,2,3}, {4,5,6}, {7,8,9} }; //按行全部初始化
3、int aa[ 3 ][ 3 ]={{1,2},{4},{8}} //按行部分初始化;
4、int aa[ ][ 3 ]={1,2,3,4,5,6,7,8,9}; //全部初始化的时候可以省略第一维的长度
//在对部分元素初始化的时候,也可以省略第一维长度,但应该采用分行初始化
int aa[ ][ 3 ]={{1,2},{4},{8}}
C语言要求定义二维数组时必须指定第二维的长度,如:int ( *p )[ 3 ].
我们可以看到,指向二维数组的指针,本质上是一个指针数组,这个数组里的每一个指针都指向一个一维数组;
例如: int aa[][3]={ {1,2,3}, {4,5,6}, {7,8,9} };
编译器把数组名字"aa"看成是 :"int (*)[3]"
其中"[3]"不可省略,因为它指明了该指针的单位1的长度是3个int型,我们定义对应指向二维数组的指针的时候,一定要考虑到
实际上我们定义的是一个指针数组.
PS:添加一个小例子: