C语言---数组的声明与二维数组的模拟--数组与指针
语言中指针与数组这两个概念之间的联系是密不可分的,以至于如果不能理解一个概念,就无法彻底理解另一个概念。
C语言中的数组值得注意的地方有以下两点:
C语言中只有一维数组,而且数组的大小必须在编译期就作为一个常数确定下来。然而,C语言中数组的元素可以是任何类型的对象,当然也可以是另外一个数组。这样,要“仿真”出一个多维数组就不是一件难事。
对于一个数组,我们只能够做两件事:确定该数组的大小,以及获得指向该数组下标为0的元素的指针。其他有关数组的操作,哪怕它们看上去是以数组下标进行运
算的,实际上都是通过指针进行的。换句话说,任何一个数组下标运算都等同于一个对应的指针运算,因此我们完全可以依据指针行为定义数组下标的行为。
一旦我们彻底弄懂了这两点以及它们所隐含的意思,那么理解C语言的数组运算就不过是“小菜一碟”。如果不清楚上述两点内容,那么C语言数组运算就可能会给
编程者带来许多困惑。需要特别指出的是,编程者应该具备将数组运算与它们对应的指针运算融汇贯通的能力,在思考有关问题时大脑中对这两种运算能够自如切
换。毫无滞碍。
任何程序设计语言中都内建有索引运算,在C语言中索引运算是以指针算术的形式来定义的。
如何声明一个数组
要理解C语言中数组的运作机制,我们首先必须理解如何声明一个数组,例如:
int a[3];
这个语句声明了a是一个拥有了3个整型元素的数组,类似的,
struct{ int p[4]; double x; }b[17];
声明了b是一个拥有17个元素的数组,其中每个元素都是一个结构,该结构中包括了一个拥有4个整形元素的数组(命名为p)和一个双精度类型的变量(命名为x)。
现在考虑下面的例子:(敲黑板:重难点开始预警)
int calendar[12][31];
然后考一考自己,calendar[4]的含义是什么?
因为calendar是一个有着12个数组类型元素的数组,它的每个数组类型元素又是一个有着31个整型数组,所以calendar[4]是 calendar数组的第五个元素,是calendar数组中12个有着31个整型元素的数组之一,因此calendar[4]的行为也就表现一个有着 31个整形元素的数组的行为,例如sizeof(calendar[4])的结果是31与sizeof(int)的乘积。
p=calendar[4];
这个语句使指针p指向了数组calendar[4]中下标为0的元素(此时,p是一个指向int类型的指针)。如果calendar[4]是一个数组,我们当然可以通过下标的形式来指定这个数组中的元素,就像下面这样:
i = calendar[4][7]; // (1)
我们确实也可以这样做。还是与前面类似的道理,这个语句可以写成下面这样而表达式的意思保持不变:
i = *(calendar[4]+7); // (2)
这个语句还可以进一步写成:
i = *(*(calendar+4)+7); // (3)
(1)(2)(3)表达的含义是一样的。
从这里我们不难发现,用方括号的下标形式很明显地要比指针来表达简便得多。下面我们再看:(这个地方我犯过错误)
p = calendar;
这个语句是非法的,因为calendar是一个二维数组,即数组的数组,在此处的上下文中使用calendar名称会将其转化为一个指向数组的指针(指向指针的指针),而p是一个指向整型变量的指针,这个语句试图将一个类型的指针赋值给另一种类型的指针,所以是非法的。
很显然,我们需要一种声明指向数组的指针的方法,经过了前面对类似问题不厌其烦的讨论,构造出下面的语句应该不需要废多大力气:
int (*ap)[31];
这个语句的效果是,声明了*ap是一个拥有三十一个整型元素的数组,ap就是一个指向这样的数组的指针,因而我们可以这样写:
int(*monthp)[31]; Monthp = calendar;
这时,Monthp和calendar都是指向指针的指针。所以赋值可以成功。
这样,monthp将指向数组calendar的第一个元素,也就是数组calendar的12个有着31个元素的数组类型元素之一。
假定在新的一年开始时,我们需要清空calendar数组,用下标形式可以很容易做到:int month; for(month=0;month < 12;month++){ int day; for(day=0; day < 31;day++) calendar[month][day]=0; }
上面的代码段如果只用指针应该如何表示呢?我们很容易地把 calendar[month][day]=0; 表示为*(*(calendar+month)+day)=0;
但是真正有关的部分是哪些呢?(重点开始)
如果指针monthp指向一个拥有31个整型元素的数组,而calendar的元素也是一个拥有31个整型元素的数组,因此就像是在其他情况中我们可以使用一个指针遍历一个数组一样,这里我们同样可以使用指针monthp以步进的方式遍历数组calendar:
int (*monthp)[31]; for(monthp=calendar;monthp < &calendar[12];monthp++){ int *dayp; for(dayp=*monthp;dayp < &(*monthp)[31];dayp++) *dayp=0; }
注:如何使一个指针变量指向另一个变量呢?可以通过赋值语句是一个指针变量得到另一个变量的地址,从而使它指向一个该变量。例如
int * pointer_1; //pointer_1是指针变量;
int * pointer_2;
pointer_1=&i;
pointer_2=&j;
将变量i的地址存放到指针变量pointer_1中,因此pointer_1就指向了变量i。对j同理。

浙公网安备 33010602011771号