Chinaunix首页 | 论坛 | 博客
  • 博客访问: 549077
  • 博文数量: 181
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1498
  • 用 户 组: 普通用户
  • 注册时间: 2013-12-22 15:17
个人简介

用发呆的时间来理清自己的思绪

文章存档

2015年(7)

2014年(134)

2013年(40)

分类: C/C++

2013-12-27 23:10:43

介绍很详细,给指针分“级”的思想很好,有种恍然大悟的感觉,感谢这位老师的分享,大家一起共同进步吧。
原文地址:http://blog.sina.com.cn/s/blog_4a6e6a1701000ape.html作者:零下#361#度
 在学习C语言的过程中,多维数组的指针是一个难点,许多初学者接受起来都感到困难,特别是对二维数组中a+i=a[i]=*(a+i)这样的等式不能理解,而在应用中对“行指针”和变量指针的运用也经常出现错误。纠其原因,主要是没有抓住问题的关键,同时又受到一维数组思维惯性的影响,不能从较高的角度来掌握问题的本质。笔者总结多年讲授C语言的教学经验,提出用“级别论”的方法来分析问题,收到了较好的效果,能够帮助初学者加深对这一问题的理解。
1 数组地址的“级别”
1.1 什么是数组地址的“级别”?
  为了有助于对问题的理解,我们人为地给数组的地址“定级”,以二维数组为例,已知有如下说明语句:
  static int a[3][4];
则a+i、a[i]、&a[i][0]都表示地址,且有a=a[i]=&a[i][0],它们的区别是什么?我们说,a是“二级地址”,它是指向“行”的;a[i]是“一级地址”,它是指向元素的。归纳起来我们有如下论断:

  二维数组名+i=“二级地址”,它指向数组中的某一行,称为“行地址”;
  一维数组名+i=“一级地址”,它指向数组中的某一个元素,称为“元素地址”或“点地址”;
  作为特例,我们可以把数组元素称为“0级地址”。
1.2 各级地址的取值范围
  二级地址的取值范围是各行的首地址,亦即每一行第一个元素的地址,因此有a+i=&a[i][0];而一级地址的取值范围是所有元素地址值,因此有a[i]+j=&a[i][j]。由此可以看出,一、二级地址的值域有相交的部分。当一、二级地址都取某一行的首地址时,它们的值便相等了。此时便有: a+i=a[i]=*(a+i)=&a[i][0]。
1.3 推广到一般情况
  对于三维数组,我们有:
  三维数组名+i=“三级地址”,它指向数组中的某一平面,称为“层地址”;
  二维数组名+i=“二级地址”,它指向数组中的某一直线,称为“行地址”;
  一维数组名+i=“一级地址”,它指向数组中的某一个元素,称为“点地址”。
  例如int a[3][4][5];是一个三维数组,则a表示三级地址,a[0]表示二级地址,a[0][0]表示一级地址,而a[0][0][0]则表示元素(0级地址)。
  用此方法,我们可以推广到n维数组,n维数组中的最高级地址是“n级地址”。当然超过三维时,我们便难以给出它的几何解释。
2 运算符*与[]的作用
  在表示多维数组的指针时,数组名与指针运算符*和下标运算符[]紧密的结合在一起,此时两者的作用是等价的,它们都起到“降级”的作用。若a表示二级地址,则a[0]和*a表示一级地址,a[0][0]和**a则表示元素。由此可以看出,每增加一个*或[],地址的级别就下降一级,在这里*和[]可以混合使用,例如*(a[i]+j ),*(*(a+i)+j), a[i][j]都表示二维数组中第i行第j列的元素。判断一个指针常量或变量的“级别”只需查看表达式中*与[]的个数便一目了然了。
3 指针变量的“级别”
  与指针常量(地址)相对应指针变量也有它的“级别”。指针变量的级别是由其定义方式决定的。
3.1 设p为指针变量,若其定义语句为int (*p)[n]则p为二级指针变量,它的初值也只能是二级地址,此时p+1指向下一行,亦即“二级指针按行移动”。
  例1、输出二维数组任一行任一列元素的值
  main ()
  { static int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};
  int i,j,(*p)[4];/* 定义二级“行指针”p */
  p=a; /*二级指针变量的初值为二级地址 */
scanf (″i=%d, j=%d ″, &i, &j);
  printf (″a[%d, %d]=%d\n ″,i,j,*(p+i)+j));
  }
  运行结果:
  i=1, j=2
  a[1,2]=13
3.2 设p为指针变量,若其定义语句为 int *p;则p为一级指针变量,它的初值也只能是一级指针,此时p+1指向“下一个元素”,亦即一级指针按元素移动。
  例2、用指针变量输出数组元素的值。
  main ()
  { static int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};
  int i, (*p) /* 定义一级p */
  p=a[0]; /*一级指针变量的初值只能是一级地址 */
  for (p=a[0]; p
  {if ((p-a[0])%4==0) printf (″\n ″)
  printf (″%4d ″, *p);
  }
  }
  运行结果:
  1  3  5  7
  9  11 13 15
  17 19 21 23
  虽然在二维数组中a=a[0]=&a[0][0],但在例1中对指针变量赋值的语句只能写成p=a;而不能写成p=a[0]或p=&a[0][0];而在例2中,由于a[0]或&a[0][0]都是一级地址,所以p=a[0]可以代换成p=&a[0][0]。
3.3 设p为指针变量,若其定义语句为 int (*p)[n][m]则p为三级指针变量,它的初值是三级指针,此时p+1指向下一层,亦即三级指针按层移动。
  例3、输出三维数组某一行某一列元素的下标值
  main ()
  {static int a[2][3][4]
  ={1,3,5,7,
 9,11,13,15,
 17,19,21,23,
 25,27,29,31,

 33,35,37,39,
 41,43,45,47};
  int i,j,k,m;
  int (*p) [3][4];/* 定义一个三维的层指针 */
  p=a; /* 把三级地址赋给三级指针变量 */
  printf (″a[i][j][k]= ″);
  scanf (″%d ″, &m);
  for (i=0; i<2; i++)
  for (j=0; j<3; j++)
  for (k=0; k<4; k++)
  if(*(*(*(p+i)+j)+k)==m)
  printf (″i=%d, j=%d, k=%d\n ″, i+1,j+1,k+1);
  }
  运行结果:
  a[i][j][k]=45
  i=2,j=3,k=3
  例1、例2为谭浩强编C程序设计教材中的例题,例3为自编例题。
  所有程序在PC486/DX66、Turbo C 2.0环境下调试通过。
阅读(1358) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~