一、指针与一维数组
我们常说的指针就是指针变量的意思,注意他也是变量,指针与普通的变量有区别也有联系
普通的变量相当于一个容器,容器里面存储了数值,用到了这个变量就相当于直接取走了这个数值
而指针存储的是内存地址,什么是内存地址呢?假设定义一个普通变量a,定义完成之后,系统会
在内存中给这个变量分配一片存储空间,这个存储空间的名字就叫做a,这个存储空间里面放的就
是数据,为了区分各个存储空间,就给这个存储空间分配一个地址,这个地址就是这个变量所在的
地方,程序运行的时候就很快能找到,地址就相当于一个编号。
由于数组的数组名就是指针,也就是存储了数组首元素的地址,因此会有下面两种方式:
int *p,a[10];
p=a;
p=&a[0];
由于都是指针,因此p与a可以直接相等,而从数组方面来说的话,p又指向了数组首元素,并且存
储了它的地址,我们可以得出一个结论:指针的本质就是存储地址;
&数组名[某数] = 数组名 + 某数
数组名[某数] = *(数组名 + 某数)
1.1 指针遍历数组
可以直接通过数组下标直接遍历数组,如何通过指针遍历数组呢?我们只需要将数组首元素
的地址传给指针,就可以操作数组的元素了;
void test(int *p,int n){
int i,sum=0;
for(i=0;i<n;i++){
sum+=*(p+i); //这里的p+i指的是偏移首元素的地址,然后再用操作符取出来即可;
}
return;
}
注意:(p+i)式子里面的i不能是浮点数,因为地址是按照字节来的,根据数据类型来看,int类
型只能4个字节4个字节的往前走,不可能存在小数个字节的;
1.2 为何要引出指针
1.2.1 指针与数组的传递
函数是可以接受数组的指针作为参数的,这样可以避免将整个数组都复制到函数中去,减少了内存
和时间的开销,例如如下:
void test(int *arr,int size)
注意:上面是指向数组的指针,并不是数组本身;
1.2.2 数组作为函数的返回值
函数可以返回指向数组的指针,例如在函数内部动态的分配数组内存,然后返回指向该数组的指针
二、 指针与二维数组
首先要明确一点,二位数组的结构是怎样的?简单写一个二维数组,看看元素地址的排列。
#include <stdio.h>
int main()
{
int n,i,j;
scanf("%d",&n);
int a[n][n];
printf("Enter %d integres!\n",n*n);
for(i=0;i<n;i++){
for(j=0;j<n;j++){
scanf("%d",&a[i][j]);
printf("%p\n",&a[i][j]); //%p表示地址格式化操作符,
}
}
return 0;
}
下面是运行的结果:这里说明一下,在内存中地址是按十六进制排列的,0-9,A-F,逢十六
进一,由于元素是int 类型的,因此会按照0->4->8的顺序走,8+4=12,也就是对应十六进制的C
12+4=16,逢十六进一,所以前面的6加一,从这里我们可以看出,二维数组是按照Z字型排列的
,通俗一点就是说按照行优先排列的,这就意味着每一行都存储在连续的内存块中,而指向下一
行的指针则指向下一个连续内存块的起始地址。
2.1 指针与二维数组的关系
类比一维数组,二维数组名也是一个指向数组的指针,例如int a[3][4],a表示是一个指向
整型数组的指针,且指向数组的第一行,存储的是是第一行的地址,存储的也是第一行首元素的地
址,我们接下来举个看个代码来验证这一结果性。
注意:看看是不是我们想的那样,运行结果如下所示:
从上图我们可以看出,第一行的地址其实就是第一行首元素的地址,同理可得,其它行的地址也
是存储的该行首元素的地址。因为a是二级指针,a+1指的就是存储了第二行初始元素的地址,就
是相当于a+1是一个标识符,指针变量的名字就叫做a+1,通过操作符取值可以把里面的地址的值
取出来,即*(a+1),这个*(a+1)代表着的是第二行首元素的地址,也就是一级指针了,就跟我i们上
面讲述的一级指针与一维数组的关系一致了,如果要取值这一行元素的话,*(*(a+1)+j),其中j
表示的是偏移首元素的偏移量,0<=j<len,len表示的是该行的元素个数。
下面总结一下,二级指针与二维数组的关系:
1、 *(a+i)+j = &a[ i ] [ j ]
2、*( *(a+i)+j) = a[ i ] [ j ]
特别是上式第一个,主要是取元素的地址的,在一维数组中有这样的关系,p[ i ] = *(p+i)
其中p是一级指针,同理可得*(a+i) =a[ i ],不过这里的是二级指针,也就是说a[ i ]才是一级指针,
存的是该行元素的首地址,然后就是*(a[ i ] +j) = a[ i ] [ j ];自己可以去试验一下。