关于c语言二维数组与指针的个人理解及处理办法。
相信大家在学习C语言时,对一维数组和指针的理解应该是自信的,但是,我在学习过程中,看到网上一些博文,发现即便是参加工作的一些专业编程人员,突然碰到二维数组和指针的问题时,也可能会遇到难以处理的诡异问题,并且问题一出现,很难一时间解决。
我自学已经1个多月了,对C语言了解还很浅薄。学到数组和指针的时候,我看了大量的博文和书籍并亲自动手实践,做了一些总结,希望和大家分享交流,若有错误和不足之处,希望大家好不客气的提出,以免误导他人。
好了,现在开始。
我对二维数组和指针的处理划分为两类:降维法,线性连续法。(这仅仅是我自己命命名而已)。
1) 降维法 。
我记得在一本日本作家的书里看到过这样一个理念:C语言其实没有所谓的“二维(多维)数组”。此说法的 依据是:拿二维数组来说,其实就是一个特殊的一维数组,特殊在于它里面的元素又是若干个数组。若把里面的数组看做是一个元素,那么,这个数组就是普通的一维数组了。降维法的思想就是如此。
如何降维?
例如:int arr[3][2]={{1,2},{3,4},{5,6}}; 我们去掉arr[3],就剩下int [2],那么int[2]就是降维后的“一维数组”的 元素的类型,也就是说:{1,2} 和 {3,4}和{5,6} 这3个元素的类型是int[2]型。现在,你就把这个数组当做是一 维数组看待吧。同样,我们定义一个指针去指向这个数组,当然这个指针的类型必须要和这个“一维数组”的 类型一致,所以,定义为:int (*p)[2] (请注意这个与int*p[2]的区别) 。接下来就是让指针变量p指向数组 了,和一维数组一模一样, p=arr 或者 p=&arr[0]。下面我们来多数组进行处理。
# include <stdio.h>
int main (void)
{
int arr[3][2]={{1,2},{3,4},{5,6}};
int i,j;
int (*p)[2]=arr; //或者= &arr[0]
for(i=0;i<3;i++)
for(j=0;j<2;j++)
printf("%d\n", *(arr[i]+j) ) //或者 *(*(arr+i)+j ) ,因为arr[i]等价于*(arr+i)
return 0;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
函数形式:
# include <stdio.h>
void test( int (*a)[2] , int row )
{
int i,j;
for(i=0;i<row;i++)
for(j=0;j<2;j++)
printf("%d\n",*(*(a+i)+j) );
}
int main (void)
{
int arr[3][2]={{1,2},{3,4},{5,6}};
int (*p)[2]=arr ; //或者= &arr[0]
test(p,3); //其实也可以不用定义P指针,直接发送arr或者&arr[0]也可以
return 0;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
函数形式:情景:找出一个二维数组每行的最大值,并输出。
# include <stdio.h>
void test(int (*a)[2],int row) //形参是“一维数组的地址”和 行数。
{
int max;
for(int i=0;i<row;i++) //用i控制行
{
max=a[i][0]; //假定每行第一个元素最大
for(int j=1;j<2;j++) //每行第以最大,那么就从每行第2个数开始就可以了,即j=1;
if( *(*(a+i)+j)>max ) 或者 //if(*(a[i]+j)>max)
max= *(*(a+i)+j); 或者 // max=*(a[i]+j);
printf("%d\n",max); //输出最大值
}
}
int main(void)
{
int arr[5][2]={{5,2},{31,4},{5,63},{34,555},{131,1}};
int (*p)[2]=arr //或者=&arr[0]
test(p,5);
return 0;
}
线性连续法:
我们要知道:二维(多维)数组的最基本元素在内存中的储存方式是线性连续的,而不是平面的。
如上图:定义一个二维数组:int a[3][4]={{1,3,5,7},{9,11,13,15},{17,19,21,23}},假定2000是元素1的地址,我 们发现这个数组的最基本元素的地址是连续的,于是我们就可以用这个属性来处理二维数组。
比如我们在对一个二维数组通过scanf函数初始化的时候(或者全部输出),这时不会考虑二维数组形式上的 问题(如他是几行,几列),我们只是把他们一个一个赋值而已,可以这样。
# include <stdio.h>
int main (void)
{
int arr[3][4];
int *p=&arr[0][0];
int i , len=3*4;//总最基本元素个数
for(i=0;i<len;i++)
scanf("%d",p++); //有人会怀疑p++是否正确,那请你去弄清a=i++ 和a= ++ i的区别。
p=&arr[0][0]; //请特别注意这条语句的作用。想想他是干什么用的。没有他会怎么样。
for(i=0;i<len;i++) //p每增加1,就变成了下一个最基本元素的地址,由1的地址变为3的,5的,7的,9的,11 //的...
printf("%d\n",*p++);
return 0;
}
有人会说:这种方法不方便对二维数组以矩阵的形式处理,请看接着看。
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
函数形式:情景:找出一个二维数组每行的最大值,并输出。
# include <stdio.h>
void test(int*a,int row,int col) //定义函数,形参为:整形指针,行数,列数。
{
int i, j, max;
for(i=0;i<row;i++) //用i控制行
{
max=*(a+i*col+0); //假定每行第一个元素最大
for(j=1;j<col;j++) //通过循环对每行的元素间进行比较,确定最大值。注意;这里j从1开始,而不是0
if( *(a+i*col+j)>max ) //当然也可以从0开始,不过那样就重复比较了。
max=*(a+i*col+j);
printf("%d\n",max); 输出每行的最大值。
}
}
int main(void)
{
int arr[3][2]={{351,12},{1,45},{78,110}};
int *p=&arr[0][0]; //取第一个最基本元素的地址
test(p,3,2); //发送地址,行数 列数
return 0;
}
我们会发现,线性连续法在取数组地址的时候很简单粗暴,就是取数组的第一个最基本元素就OK了,如果想要重 新利用二维数组的矩阵形式,这里用了一个小技巧,请看: *(a+i*col+j)它表示每个最基本元素
,简单起见,我 们把col换成眼前问题的列数2,也即是*(a+i*2+j),首先明确:括号里面的是每个基本元素的地址,a是起始地址, 是一个导火索,i*2 是用来让地址“换行”的,j则是让地址在i确定(即一个行)的情况下遍历这行的每个元素的地 址。请牢记:i*col, 这里的col是列数。
写在最后:第一次写博客。所以,存在错误也请大家谅解。希望大家踊跃提出意见。谢谢。
date :2015-02-12 21:58
最新文章
- js中的文本编辑器控件KindEditor---那些打酱油的日子
- NodeJS入门(五)—— process对象
- web app上传图片
- js替换选中的文字
- 数字与字母 随机数小demo
- 关于centos7的网络配置
- css渐变颜色在线制作
- Java设计模式系列1--原型模式(Prototype Method)
- ubuntu 12.04 设置代理
- Hibernate 中createQuery与createSQLQuery
- ant -verbose -debug ...
- 学习 opencv---(9)形态学图像处理(一):膨胀和腐蚀
- splice 操作符
- css系列教程--margin padding column(完结)
- css3动画与js动画的一些理解
- 微信JS-SDK 选取手机照片并进行上传
- Mysql连接问题:com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException
- ARIMA模型原理
- 浅谈Java中的锁:Synchronized、重入锁、读写锁
- Flask简述