|  首页  |  资讯  |  评测  |  活动  |  学院  |  访谈  |  专题  |  杂志  |  产服  |  
您现在的位置:硅谷网> 学院> 论文>

基于C++二维数组的几个问题研究

2013-02-08 10:49 作者:沈 鹏 来源:硅谷网-《硅谷》杂志 HV: 编辑: 【搜索试试
  据《硅谷》杂志2012年第22期刊文称,二维数组使用一般有两种情况,一种是描述一个二维的事物。比如用1表示墙,用0表示通路,我们可以用二维数组来描述一个迷宫地图;用1表示有通路,0表示没有通路,我们可以用二维数组来描述几个城市之间的交通情况。还有一种是描述多个具有多项属性的事物。比如有多个学生,每个学生有语文、数学和英语三门成绩,我们就可以用二维数组来描述。对二维数组使用过程中的几个问题进行探究。
  关键词:C++;二维数组;动态分配;参数;指针
  C++程序中的new[]和delete[]作为动态内存分配的重要手段在程序设计中有着广泛应用,尤其应用在程序员自定义的类与结构的数组声明上。但由于C++程序语言中并没有给出显示的数组访问限制[1],极易造成"数组越界"的错误。这种错误会引起对非程序数据段的修改,而使得程序崩溃。
  1C++中二维数组的动态分配
  在C++中动态分配二维数组可以先申请一维的指针数组,然后该数组中的每个指针再申请数组,这样就相当于二维数组了,但是这种方法会导致每行可能不相邻,从而访问效率比较低。那么什么是真正的二维数组呢?C语言中的二维数组在内存组织形式是按行存储的连续的内存区域。所以,必须保证数组元素是按行存储的,而且也是最重要的是内存要连续。
  所以,笔者设计如下的一个方法:
  假定二维数组的元素变量类型是MyType;可以是C语言接受的除void之外的任何类型,因为编译器不晓得void类型的大小;例如int,float,double等等类型;
  introw=2;/////暂假定行数是2,这个可以在运行时刻决定;
  intcolumn=3;/////暂假定列数是2,这个可以在运行时刻决定;
  void**ptdhead=NULL;//////////在后面说明为什么要用void**类型
  void**ptdBody=NULL;//////////在后面说明为什么要用void**类型
  ptdhead=(void**)malloc(sizeof(void*)*row+sizeof(MyType)*row*column);
  if(!ptdhead)
  returnFALSE;
  ptdBody=ptdhead+row;
  for(intncount=0;ncount<row;ncount++)
  ptdhead[ncount]=ptdBody+ncount*column*sizeof(MyType)/sizeof(void*);
  MyType**ptdheadRealse;
  ptdheadRealse=(MyType**)ptdhead;///////////////////强制转换为自己程序需要的二维数组元素类型的指针
  ptdhead=NULL;
  for(inti=0;i<row;i++)
  {
  for(intj=0;j<column;j++)
  {ptdheadRealse[i][j]=i+j;////////进行简单的初始化;}
  }
  这样的一种方法动态分配的二维数组,内存是连续的,是真正意义的C语言二维数组,满足所有二维数组访问的方法,而且内存利用效率高,程序性能好。
  2C++二维数组的传递
  用二维数组作为参数传递(用二维数组处理矩阵),但是希望接受传递二维数组参数的函数可以处理任意维度的数组(希望矩阵的行数和列数都是不固定的)。但一般传递二维数组的基本规则好像是这样的:可以用二维数组名作为实参或者形参,在被调用函数中对形参数组定义时可以可以指定所有维数的大小,也可以省略第一维的大小说明。如:
  voidFunc(intarray[3][10]);voidFunc(intarray[][10]);
  二者都是合法而且等价,但是不能把第二维或者更高维的大小省略,如下面的定义是不合法的:voidFunc(intarray[][]);将二维数组当作参数的时候,必须指明所有维数大小或者省略第一维的,但是不能省略第二维或者更高维的大小,这是由编译器原理限制的。但是我们在编写程序的时候却需要用到各个维数都不固定的二维数组作为参数,这就难办了,编译器不能识别阿,怎么办呢?不要着急,编译器虽然不能识别,但是我们完全可以不把它当作一个二维数组,而是把它当作一个普通的指针,再另外加上两个参数指明各个维数,然后我们为二维数组手工寻址,这样就达到了将二维数组作为函数的参数传递的目的,根据这个思想,我们可以把维数固定的参数变为维数随即的参数。
  3C++中二维数组形参的传递
  voidFunc(intarray[3][10]);voidFunc(intarray[][10]);可以省略第一维的大小,错误的是voidFunc(intarray[][].这样的用法只能在初始化时可以用);这样写也是错误:voidFunc(constintm,constintn,intarray[m][n]);或voidFunc(intm,intn,intarray[m][n]);大家都知道数组的索引必须是个常量表达式,voidFunc(constintm,constintn,intarray[m][n]);如果constintm没有初始化,那么系统将m或n自动初始化为0,所以这样些是不对的,如果我们采用这样voidFunc(int**array,intm,intn)的形式,那么在实际的函数调用是,我们就要进行强制转换才可以用,我们可以这样调用voidFunc((int**)array,intm,intn);在函数调用时,要把数组形式写成指针形式如*((int*)array+n*i+j);直接写intarray[i][j]会导致错误,编译可以通过,在VC编译器中执行会出现异常,DEV编译器会出现一个随机值,原因就在于如果写成intarray[i][j],编译器无法正确的寻址,当然各种编译器对它的处理结果是不一样的。如果我们的形参是数组,那么我们在函数体中可以用指针也可以用数组形式,但是如果我们形参数中用的是指针,最好也用指针,有时用数组形式会出错,二维数组就是这样。
  4二维数组中的指针问题
  1)用指针表示二维数组元素。要用指针处理二维数组,首先要解决从存储的角度对二维数组的认识问题。我们知道,一个二维数组在计算机中存储时,是按照先行后列的顺序依次存储的,当把每一行看作一个整体,即视为一个大的数组元素时,这个存储的二维数组也就变成了一个一维数组了。而每个大数组元素对应二维数组的一行,我们就称之为行数组元素,显然每个行数组元素都是一个一维数组。
  2)用二维数组名作地址表示数组元素。我们还可以得到二维数组元素的一种表示方法:对于二维数组a,其a[0]数组由a指向,a[1]数组则由a+1指向,a[2]数组由a+2指向,以此类推。因此,*a与a[0]等价、*(a+1)与a[1]等价、*(a+2)与a[2]等价,┅,即对于a[i]数组,由*(a+i)指向。由此,对于数组元素a[i][j],用数组名a的表示形式为:*(*(a+i)+j)。指向该元素的指针为:*(a+i)+j。数组名虽然是数组的地址,但它和指向数组的指针变量不完全相同。指针变量的值可以改变,即它可以随时指向不同的数组或同类型变量,而数组名自它定义时起就确定下来,不能通过赋值的方式使该数组名指向另外一个数组。
  3)行数组指针。在上面的说明中我们已经知道,二维数组名是指向行的,它不能对如下说明的指针变量p直接赋值:inta[3][4]={{10,11,12,13},{20,21,22,23},{30,31,32,33}},*p;其原因就是p与a的对象性质不同,或者说二者不是同一级指针。C语言可以通过定义行数组指针的方法,使得一个指针变量与二维数组名具有相同的性质。行数组指针的定义方法如下:数据类型(*指针变量名)[二维数组列数];例如,对上述a数组,行数组指针定义如下:int(*p)[4];它表示,数组*p有4个int型元素,分别为(*p)[0]、(*p)[1]、(*p)[2]、(*p)[3],亦即p指向的是有4个int型元素的一维数组,即p为行指针此时,可用如下方式对指针p赋值:p=a;
  下面说明一下,我碰到的问题,我们定义了一下如下的函数:voidfunction(double**array,intwidth,intheight)。
  然后我们定义了一个二维数组doublep[3][3]={{1,2,3},{4,5,6},{7,8,9}};
  当我们调用function时,即function(p,3,3),编译器会报错:
  errorC2664:'function':cannotconvertparameter1from'double[3][3]'to'double**'
  参数传递实际上是一个赋值的过程,为了便于说明我们底下都以赋值的方式加以说明。
  我们知道p是数组首地址,地址指向的是第一个行数组,在某种程度上来说可以把二维数组名理解为指针的指针,但是这两者是有区别的。
  double*p[3]和double(*p)[3]
  double*p[3]是一个指针数组,它是一个数组,里面存放了3个指针;double(*p)[3]它是一个数组指针,它是一个指针,这个指针指向的是一个数组,它和二维数组有相同的性质,具体说明可以看下分割线中红色的字体所示的部分,由此我们可以知道如下的赋值是可行的:doublep[3][3]={{1,2,3},{4,5,6},{7,8,9}};
  double(*pp)[3]=p;
  这里实际上的话也是应该执行了一次上面所说的自动转化,p转化了一个指向行数组的指针,然后赋值给了数组指针变量pp;另外,我们发现底下的赋值也是可行的:
  double*p[3];
  double**pp=p;
  这里实际上也是执行了一次上面所说的转化,p转化了一个指向指针变量的指针,然后赋值给了pp;这里看下,上面两次转化后唯一的的区别于一个是指向数组的指针,一个是指向指针的指针,而C++不允许接下来的再次转化,说明C++只支持数组到指针的一次转化,而二次转化没有支持。
【对“基于C++二维数组的几个问题研究”发布评论】

版权及免责声明:
① 本网站部分投稿来源于“网友”,涉及投资、理财、消费等内容,请亲们反复甄别,切勿轻信。本网站部分由赞助商提供的内容属于【广告】性质,仅供阅读,不构成具体实施建议,请谨慎对待。据此操作,风险自担。
② 内容来源注明“硅谷网”及其相关称谓的文字、图片和音视频,版权均属本网站所有,任何媒体、网站或个人需经本网站许可方可复制或转载,并在使用时必须注明来源【硅谷网】或对应来源,违者本网站将依法追究责任。
③ 注明来源为各大报纸、杂志、网站及其他媒体的文章,文章原作者享有著作权,本网站转载其他媒体稿件是为传播更多的信息,并不代表赞同其观点和对其真实性负责,本网站不承担此类稿件侵权行为的连带责任。
④ 本网站不对非自身发布内容的真实性、合法性、准确性作担保。若硅谷网因为自身和转载内容,涉及到侵权、违法等问题,请有关单位或个人速与本网站取得联系(联系电话:01057255600),我们将第一时间核实处理。
广告
相关
·基于视频会议终端QoS(服务质量)技术方案探析
·基于学习兴趣培养的《C语言程序设计》教学研究
·基于“面向服务架构”SOA的PLM系统浅析
·基于LPC1114的加窗差值FFT算法的谐波检测设计
·基于SDM模型的250T转炉钢包底吹模型开发
·《硅谷》杂志:基于制品挤压方法的研究
·基于C/S模式的学生学籍信息管理系统的设计与实现
·基于机构运动精度的平稳性车辆轮轴探伤研究
头条
硅谷网解密:4G网络中的微波传输解决方案 硅谷网解密:4G网络中的微波传输解决方案
在2013年12月4日,工信部向中国移动、中国联通、中国电信颁发TD-LTE(4G)经营许可之后……
·硅谷网解密:4G网络中的微波传输解决方案
·创意产业的批量化规律 工业造型方法论之加减
·《硅谷》杂志:浅谈电信运营商开展IPTV业务
·《硅谷》杂志:新型桌面搜索关键技术的研究与
·硅谷杂志:基于时间技术的搜索引擎排名算法
图文
佳惠安抗菌喷剂敷料杀(抑)菌临床检验结论
佳惠安抗菌喷剂敷料杀(抑)菌临床检验结论
利用重力势能做功发电介绍和势能输出系统介绍
利用重力势能做功发电介绍和势能输出系统介
佳惠安抗菌喷剂敷料杀(抑)菌临床检验结论
佳惠安抗菌喷剂敷料杀(抑)菌临床检验结论
利用重力势能做功发电介绍和势能输出系统介绍
利用重力势能做功发电介绍和势能输出系统介
最新
·佳惠安抗菌喷剂敷料杀(抑)菌临床检验结论
·利用重力势能做功发电介绍和势能输出系统介绍
·李磊:新时代下电网调度自动化技术的发展分析
·提升企业竞争力以及企业人力资源管理优化思考
·《硅谷》杂志:采油分层测静压工艺技术浅究
热点
·判断连续时间系统的线性非时变性和因果性
·3DMAX+Vary室内漫游动画制作的技法浅析
·长期使人困惑的问题:TCP连接中断的实时检测
·佳惠安抗菌喷剂敷料杀(抑)菌临床检验结论
·关于汽轮机油系统失火原因分析及防范措施的一
旧闻
·博物馆数字化展示应用研究
·探讨气体检测中如何应用数字信号处理技术
·硅谷杂志:关于网络安全解决方案的探讨
·徐海:智能变坡水槽控制系统的设计与实现
·硅谷杂志:云计算在飞行试验数据处理中的探索
广告
硅谷影像
佳惠安抗菌喷剂敷料杀(抑)菌临床检验结论
佳惠安抗菌喷剂敷料杀(抑)菌临床检验结论
利用重力势能做功发电介绍和势能输出系统介绍
利用重力势能做功发电介绍和势能输出系统介绍
公关负责人离职背后:危机公关案例分析
公关负责人离职背后:危机公关案例分析
硅谷网解密:4G网络中的微波传输解决方案
硅谷网解密:4G网络中的微波传输解决方案
使用Autoit脚本在虚拟内存盘设置考试模拟系统
使用Autoit脚本在虚拟内存盘设置考试模拟系统
探秘开滦集团设备租赁管理系统的设计和实现
探秘开滦集团设备租赁管理系统的设计和实现
关于我们·About | 联系我们·contact | 加入我们·Join | 关注我们·Invest | Site Map | Tags | RSS Map
电脑版·PC版 移动版·MD版 网站热线:(+86)010-57255600
Copyright © 2007-2020 硅谷网. 版权所有. All Rights Reserved. <京ICP备12003855号-2>