Chinaunix首页 | 论坛 | 博客
  • 博客访问: 89956
  • 博文数量: 99
  • 博客积分: 55
  • 博客等级: 民兵
  • 技术积分: 510
  • 用 户 组: 普通用户
  • 注册时间: 2012-03-20 21:29
文章分类

全部博文(99)

文章存档

2013年(5)

2012年(94)

我的朋友

分类:

2012-10-26 21:45:15

从前面的讨论中,我们不难得出一个推论,*a即数组a中下标为0的元素的引用。例如,我们可以这样写:

1*a=84;

这个语句将数组a中下标为0的元素的值设置为84.同样道理,*(a+1)数组a中下标为1的的元素的引用,以此类推,概而言之,*(a+i)即数组中下标为i的元素的引用,这种写法是如此常用,因此被简记为a[i].

正是这一概念让C语言新手难于理解,实际上,由于a+i与i+a的含义一样,因此a[i]和i[a]也具有同样的含义。也许某些汇编语言程序员会发现后一种写法很熟悉,但我们绝对不推荐这种写法。

现在我们可以考虑二维数组了,正如前面所讨论的,它实际上是以数组为元素的数组,尽管我们也可以完全依据指针编写操纵一维数组的程序,这样做在一维情形下并不困难,但是对于从记法上的便利性来说采用下述形式就几乎是不可替代了。还有,如果我们仅仅使用指针来操纵二维数组,我们将不得不与C语言中最为“晦暗不明”的部分打交道,并常常遭遇到潜伏着的编译器bug。

让我们回过头来再看前面的几个声明:

1int calendar[12][31];
2int *p
3int i;

然后考一考自己,calendar[4]的含义是什么?

因为calendar是一个有着12个数组类型元素的数组,它的每个数组类型元素又是一个有着31个整型数组,所以calendar[4]是 calendar数组的第五个元素,是calendar数组中12个有着31个整型元素的数组之一,因此calendar[4]的行为也就表现一个有着31个整形元素的数组的行为,例如sizeof(calendar[4])的结果是31与sizeof(int)的乘积。

1p=calendar[4];

这个语句使指针p指向了数组calendar[4]中下标为0的元素。如果calendar[4]是一个数组,我们当然可以通过下标的形式来指定这个数组中的元素,就像下面这样:

1i = calendar[4][7];

我们确实也可以这样做。还是与前面类似的道理,这个语句可以写成下面这样而表达式的意思保持不变:

1i = *(calendar[4]+7);

这个语句还可以进一步写成:

1i = *(*(calendar+4)+7);

从这里我们不难发现,用方括号的下标形式很明显地要比来表达简便得多。下面我们再看:

1p = calendar;

这个语句是非法的,因为calendar是一个二维数组,即数组的数组,在此处的上下文中使用calendar名称会将其转化为一个指向数组的指针,而p是一个指向整型变量的指针,这个语句试图将一个类型的指针赋值给另一种类型的指针,所以是非法的。

很显然,我们需要一种声明指向数组的指针的方法,经过了前面对类似问题不厌其烦的讨论,构造出下面的语句应该不需要废多大力气:

1int (*ap)[31];

这个语句的效果是,声明了*ap是一个拥有三十一个整型元素的数组ap就是一个指向这样的数组的指针,因而我们可以这样写:

1int(*monthp)[31];
2Monthp = calendar;

这样,monthp将指向数组calendar的第一个元素,也就是数组calendar的12个有着31个元素的数组类型元素之一。

假定在新的一年开始时,我们需要清空calendar数组,用下标形式可以很容易做到:

1int month;
2 
3for(month=0;month < 12;month++){
4    int day;
5    for(day=0; day < 31;day++)
6        calendar[month][day]=0;
7}

上面的代码段如果才用指针应该如何表示呢?我们很容易地把 calendar[month][day]=0; 表示为*(*(calendar+month)+day)=0;

但是真正有关的部分是哪些呢?

如果指针monthp指向一个拥有31个整型元素的数组,而calendar的元素也是一个拥有31个整型元素的数组,因此就像是在其他情况中我们可以使用一个指针遍历一个数组一样,这里我们同样可以使用指针monthp以步进的方式遍历数组calendar:

1int (*monthp)[31];
2for(monthp=calendar;monthp < &calendar[12];monthp++){
3    int *dayp;
4    for(dayp=*monthp;dayp < &(*monthp)[31];dayp++)
5    *dayp=0;
6}

到目前为止,我们一路行来几乎是“如履薄冰”,而且已经走得很远,在我们跌跤之前,最好趁早悬崖勒马。尽管本节中最后一个例子是合法的ANSI C程序,但是作者还有找到一个能够让该程序顺利通过编译的编译器(译注:现在大多数的c编译器能够接受上面例子中的代码)。上面例子的讨论虽然有些偏离本书的主题,但是这个例子能够很好地揭示出C语言中数组与指针之间的独特的关系,从而更清楚明白地阐述这两个概念。



原文地址:

阅读(237) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~