指针与数组
C语言学到这个时候,对于指针和数组的关系应该要有一个很明确的认识,要知道两者之间的联系和区别,但是,两者的关系往往也是C语言初学者容易拎不清的东西。
C语言中的数组值得注意的地方有两点:
(1)C语言只有一维数组,数组的大小必须在编译期就作为一个常数确定下来。C语言数组的元素可以是任何类型的对象,比如整数,字符等等,当然也可以是另外一个数组。这样就可以“仿真”出一个多维数组。
(2)对于一个数组来说,我们只能做两件事情:确定该数组的大小,以及获得指向该数组下标为0的元素的指针。其他看似对于数组的操作,即使是看上去是以数组下标进行运算的,本质上来说都是通过指针来进行的。换句话说就是,任何一个数组下标的运算就等同于一个对应的指针运算。
1、数组声明
了解学习数组就需要先理解如何声明一个数组,比如,
int a[3]; 是最基本的声明方式,代表a是一个拥有3个整形元素的数组。
struct { int p[4]; double x; }b[17];
上边的声明代表的是b是一个用于17个元素的数组,这个数组的元素是一个结构体,每一个结构体内都包括一个拥有4个整形元素的数组p和一个双精度类型的变量x。
int c[12][13]; 这一个语句声明c是一个数组,该数组拥有12个数组类型的元素,其中每个元素都是一个拥有31个整形元素的数组。如果c不是用于sizeof的操作数,而是用到其他场合中,c总是被转换成指向calender数组的起始元素的指针。要想理解这段话先要回顾一下关于指针的一些定义和操作
2、指针的操作
任何指针都是指向某种变量类型的,比如
int *ip; 就是一个指向整型的指针ip,
int i; 声明一个整数
我们可以用 ip = &i; 将变量i的地址赋值给指针ip,而且我们可以给*ip赋值来改变i的值。如果给一个指针加1,这个指针指向下一个元素,同样的如果给这个指针减1,这个指针指向前一个元素。
总结数组和指针来说,如果我们一个指针指向的是数组中的一个元素,那么我们只需要给这个指针加1,就能得到指向该数组下一个元素的指针。同样的,如果给这个指针减1,得到就是指向该数组中前一个元素的指针。其他加2,加3的情况以此类推。
下面我们来分析一段代码:
int a[3]; int *ip; p = a;
这段代码中, p = a 会把数组a中下标为0的元素地址赋值给p,千万不能写成p = &a;这样一来,p指向数组a中下标为0的元素,p+1指向数组a中下标为1的元素,p+2指向数组a中下标为2的元素。以此类题,如果想要找到数组a中下标为1的元素可以写p = p+1;。
从上边的这些讨论中也可以得出另一个结论,*a就是数组a中下标为0的元素。例如写 *a = 100; 这个语句就会将数组a中下标为0的元素设置为100。类似的*(a + 1)是数组a中下标为1的元素的引用,以此类推*(a + i)就是数组a中下标为i的元素的引用,简化为a[i]。讨论到这里对于指针和数组的关系应该很清楚了。
理清楚数组和指针的关系,现在我们来说说二维数组,先声明一个二维数组,声明一个整数和一个整数指针。
int c[12][31]; int *p; int i;
之前也说了c数组的含义,c数组是一个有着12个数组类型元素的数组,每个数组类型元素又是一个有31个整型的数组。那么我们就很好理解c[1]的含义了,c[1]就是c数组的第2个元素,是c数组中12个有31个整型元素的数组之一,也就是说c[1]是一个有31个整型元素的数组。
同样的二维数组中也可以写成指针的形式,例如下边三个其实代表的是一样的:
i = c[4][7]; i = *(c[4] + 7); i = *(*(c + 4) +7);
总结来说关于数组的操作本质上都是关于指针的操作,数组与只针对的最大区别就是数组的大小必须是确定的,而指针不一定。