| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 3360 人关注过本帖, 1 人收藏
标题:二维数组与指针(教程)
只看楼主 加入收藏
fenghelong
Rank: 3Rank: 3
来 自:上海
等 级:论坛游侠
威 望:2
帖 子:209
专家分:197
注 册:2011-8-18
结帖率:26.67%
收藏(1)
 问题点数:0 回复次数:8 
二维数组与指针(教程)
二维数组与指针


  1.二维数组元素在内存中的存放方式
  在C++中,二维数组元素值在内存中是按行的顺序存放的。若定义二维整型数组a[3][3],假设编译系统为数组a分配的内存空间从1000开始到1035为止,则数组中各元素a[0][0]~a[2][2]在内存中按行存放次序如图7.6所示。因此,与一维数组类似,可用指针变量来访问二维数组元素。


  【例7.7】用指针变量输出二维数组各元素的值。
 # include <iostream.h>
 void main(void)
 { int a[3][3]={{1,2,3},{4,5,6},{7,8,9}};
  int *p=&a[0][0]; //将二维数组首地址赋给指针变量p
  for (int i=0;i<9;i++)
  { cout<<*p<<'\t'; //输出二维数组中第i个元素值
   p++; //指针变量p加1,指向下一个元素
  }
 }
  程序执行后输出结果为:
  1 2 3 4 5 6 7 8 9
  但要用上述指针变量p访问二维数组中任意指定元素a[i][j]就觉得很不方便,为此C++设计者提供另外几种访问二维数组元素的方法,为了了解访问二维数组元素的方法,必须了解三个地址概念,即:二维数组行首地址、行地址、元素地址,现介绍如下。
  

  2.二维数组行首地址


  二维数组各元素按行排列可写成如图7.7所示矩阵形式,若将第i行中的元素a[i][0]、a[i][1]、a[i][2]组成一维数组a[i] (i=0,1,2),则二维数组a[3][3]可看成是由三个一维数组元素a[0]、a[1]、a[2]组成。即:a[3][3]=(a[0],a[1],a[2]),其中:a[0]、a[1]、a[2]是分别表示二维数组a[3][3]的第0、1、2行元素。



即:a[0]=(a[0][0],a[0][1],a[0][2])
  a[1]=(a[1][0],a[1][1],a[1][2])
  a[2]=(a[2][0],a[2][1],a[2][2])
  因为数组名可用来表示数组的首地址,所以一维数组名a[i]可表示一维数组 (a[i][0],a[i][1],a[i][2])的首地址&a[i][0],即可表示第i行元素的首地址。因此,二维数组a中第i行首地址(即第i行第0列元素地址)可用a[i]表示。
  由例 7.6可知,一维数组的第i个元素地址可表示为:数组名+i。因此一维数组a[i]中第j个元素a[i][j]地址可表示为:a[i]+j ,即:二维数组a中第i行第j列元素a[i][j]的地址可用a[i]+j来表示,而元素a[i]][j]的值为:*(a[i]+j)。
  【例7.8】定义一个3行3列数组,输出每行的首地址及所有元素值。
 # include <iostream.h>
 void main(void)
 { int a[3][3]={{1,2,3},{4,5,6},{7,8,9}};
  for (int i=0;i<3;i++)
   { cout<<"a[" <<i<<"]="<<a[i]<< "="<<&a[i][0]<<endl;
     for (int j=0;j<3;j++)
    cout<<"a[" <<i<<"]["<<j<<"]="<<*(a[i]+j)<< "="<<a[i][j]<<endl;
   }
 }
  程序执行后输出:
  a[0]=0x0065FDD4=0x0065FDD4
  a[0][0]=1=1
  a[0][1]=2=2
  a[0][2]=3=3
  a[1]=0x0065FDE0=0x0065FDE0
  a[1][0]=4=4
  a[1][1]=5=5
  a[1][2]=6=6
  a[2]=0x0065FDEC=0x0065FDEC
  a[2][0]=7=7
  a[2][1]=8=8
  a[2][2]=9=9
  由此例输出结果可看出a[i]=&a[i][0] (i=0,1,2),这表明a[i]确实可以表示第i行首地址(即第i行第0列地址)&a[i][0]。
  读者应注意,由于数组在内存的地址是由操作系统动态分配,因此,实际输出的各行首地址并不会如图7.5所假设的从1000到1035。通常地址用十六进制数表示,如在本例中:第0行实际首地址是:a[0]=0x0065FDD4。第1行实际首地址是:a[1]=0x0065FDE0。第2行实际首地址是:a[2]=0x0065FDEC。

3.二维数组行地址


  为了区别数组指针与指向一维数组的指针,C++引入了行地址的概念,并规定二维数组a中第i行地址用a+i或&a[i]表示,行地址的值与行首地址的值是相同的,即:
  a+i=&a[i]=a[i]=&a[i][0]
  但两者类型不同,所以行地址a+i与&a[i]只能用于指向一维数组的指针变量,而不能用于普通指针变量,例如:
  int a[3][3];
  int *p=a+0;
  则编译第二条指令时将会出错,编译系统提示用户p与a+0的类型不同。如果要将行地址赋数组指针变量,必须用强制类型转换,如:
  int *p=(int *) (a+0);
  关于指向一维数组的指针将在后文中介绍。
  二维数组名a可用于表示二维数组的首地址,但C++规定该首地址并不是二维数组中第0行第0列的地址(即a≠a[0][0]),而是第0 行的行地址,即a=a+0=&a[0]。

4.二维数组的元素地址与元素值
  

  知道了二维数组的行地址与行首地址后,可以讨论二维数组的元素地址。
  因为 a[i]=*&a[i]= *(a+i),所以 *(a+i) 可以表示第 i行的首地址。因此二维数组第i行首地址有三种表示方法:a[i] 、*(a+i)、&a[i][0]。
  由此可推知:第i行第j列元素a[i][j]的地址有四种表示方法:
  a[i]+j 、*(a+i)+j、&a[i][0]+j、&a[i][j]
  而第i行第j列元素a[i][j]值也有四种表示方法:
  *(a[i]+j) 、 *(*(a+i)+j)、*(&a[i][0]+j)、a[i][j]
  现将二维数组有关行地址、行首地址、元素地址、元素值的各种表示方式总结归纳如表7.1 所示:


  表7.1 二维数组a的行地址、行首地址、元素地址、元素值的各种表示方式
  行地址、元素地址、元素值 表示方式
  第i行行地址 a+i、&a[i]
  第i行首地址(第i行第0列地址) a[i]、 *(a+i)、 &a[i][0]
  元素a[i][j]的地址 a[i]+j 、*(a+i)+j 、&a[i][0]+j、&a[i][j]
  第i行第j列元素值 *(a[i]+j) 、 *(*(a+i)+j) 、 *(&a[i][0]+j)、a[i][j]
  为了加深读者对二维数组a的行地址、行首地址、元素地址、元素值的各种表示方式的理解,现举例如下:


  【例7.9】定义二维数组a[3][3],用二种方式输出行地址,用三种方式输出行首地址,用四种方式输出所有元素地址及元素值。
 # include <iostream.h>
 void main(void)
 { int a[3][3]={{1,2,3},{4,5,6},{7,8,9}};
  for (int i=0;i<3;i++)
    { cout<<"&a["<<i<<"]="<<&a[i]<<"="<<a+i<<endl; //输出第i行行地址
     cout<<"a["<<i<<"]="<<a[i]<<"="<<*(a+i)<<"="<<&a[i][0]<<endl; //行首地址
  for (int j=0;j<3;j++)
    { cout<<"&a["<<i<<"]["<<j<<"]="<<a[i]+j<<"="<<*(a+i)+j<<"="<<
     &a[i][0]+j<<"="<<&a[i][j]<<endl; //输出元素a[i][j]的地址
  cout<<"a["<<i<<"]["<<j<<"]="<<*(a[i]+j)<<"="<<*(*(a+i)+j)<<
  "="<<*(&a[i][0]+j)<<"="<<a[i][j]<<endl; //输出元素a[i][j]的值
    }
    }
 }
  程序执行后输出结果为:
  &a[0]= 0x0065FDD4=0x0065FDD4
  a[0]= 0x0065FDD4=0x0065FDD4=0x0065FDD4
  &a[0][0]= 0x0065FDD4=0x0065FDD4=0x0065FDD4=0x0065FDD4
  a[0][0]=1=1=1=1
  &a[0][1]= 0x0065FDD8=0x0065FDD8=0x0065FDD8=0x0065FDD8
  a[0][1]=2=2=2=2
  &a[0][2]= 0x0065FDDC=0x0065FDDC=0x0065FDDC=0x0065FDDC
  a[0][2]=3=3=3=3
  &a[1]= 0x0065FDE0=0x0065FDE0
  a[1]= 0x0065FDE0=0x0065FDE0=0x0065FDE0
  &a[1][0]= 0x0065FDE0=0x0065FDE0=0x0065FDE0=0x0065FDE0
  a[1][0]=4=4=4=4
  &a[1][1]= 0x0065FDE4=0x0065FDE4=0x0065FDE4=0x0065FDE4
  a[1][1]=5=5=5=5
  &a[1][2]= 0x0065FDE8=0x0065FDE8=0x0065FDE8=0x0065FDE8
  a[1][2]=6=6=6=6
  &a[2]= 0x0065FDEC=0x0065FDEC
  a[2]= 0x0065FDEC=0x0065FDEC=0x0065FDEC
  &a[2][0]= 0x0065FDEC=0x0065FDEC=0x0065FDEC=0x0065FDEC
  a[2][0]=7=7=7=7
  &a[2][1]= 0x0065FDF0=0x0065FDF0=0x0065FDF0=0x0065FDF0
  a[2][1]=8=8=8=8
  &a[2][2]= 0x0065FDF4=0x0065FDF4=0x0065FDF4=0x0065FDF4
  a[2][2]=9=9=9=9
  此例可说明表7.1中的二维数组a的行地址、行首地址、元素地址、元素值的各种表示方式是正确的。
211273085交流qq群哦,亲们。

[ 本帖最后由 fenghelong 于 2012-2-10 19:05 编辑 ]
搜索更多相关主题的帖子: 内存 void include 元素 
2012-02-10 19:02
guan2820
Rank: 1
等 级:新手上路
帖 子:1
专家分:0
注 册:2012-2-8
收藏
得分:0 
学习了
2012-02-11 14:23
weipeng1217
Rank: 5Rank: 5
等 级:职业侠客
帖 子:175
专家分:386
注 册:2012-1-12
收藏
得分:0 
。。。

C坛友交流群 群号:161091913 ,欢迎经常在线的朋友加入,一起学习,一起进步。。
2012-02-11 14:44
fenghelong
Rank: 3Rank: 3
来 自:上海
等 级:论坛游侠
威 望:2
帖 子:209
专家分:197
注 册:2011-8-18
收藏
得分:0 
回复 3楼 weipeng1217
咋咯。
2012-02-17 18:02
小鱼儿c
Rank: 9Rank: 9Rank: 9
等 级:贵宾
威 望:14
帖 子:852
专家分:1317
注 册:2011-4-1
收藏
得分:0 
文章很好,看了之后更明白许多。
谢谢分享

用心做一件事情就这么简单
2012-02-17 18:41
zd1505675319
Rank: 3Rank: 3
等 级:论坛游侠
帖 子:139
专家分:178
注 册:2011-11-4
收藏
得分:0 
复习喽
2012-02-17 18:44
fenghelong
Rank: 3Rank: 3
来 自:上海
等 级:论坛游侠
威 望:2
帖 子:209
专家分:197
注 册:2011-8-18
收藏
得分:0 
回复 5楼 小鱼儿c
嘿嘿~~
2012-02-18 17:13
a185523582a
Rank: 1
等 级:新手上路
帖 子:10
专家分:0
注 册:2012-3-26
收藏
得分:0 
...........................
2012-03-28 21:40
fenghelong
Rank: 3Rank: 3
来 自:上海
等 级:论坛游侠
威 望:2
帖 子:209
专家分:197
注 册:2011-8-18
收藏
得分:0 
回复 8楼 a185523582a
干嘛。。
2012-04-01 21:54
快速回复:二维数组与指针(教程)
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.034804 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved