前言:这是一篇简短,却满满干活的文章。带你学习指针在数组中的运用。
1.数组名的理解
int arr[4]={1,2,3,4};
其中arr是数组名,也是一个地址,他在通常情况下,和首元素地址数值相等。
其中有两个例外:
1.当数组名arr取地址,即写成&arr时,他是整个数组,取出的是整个数组的地址
比如:
#include <stdio.h>
int main()
{
int arr[4] = { 1,2,3,4 };
arr;
&arr[0];
&arr;
printf("arr=%p\n", arr);
printf("&arr[0]%p\n", &arr[0]);
printf("&arr=%p\n", &arr);
printf("arr=%p\n", arr+1);
printf("&arr[0]=%p\n", &arr[0]+1);
printf("&arr=%p\n", &arr+1);
}
通过代码运算结果我们发现,虽然这3种写法地址一样,都是首元素地址,但是给3个指针加1后,arr和 &arr[0]的地址只增加了4个字节,这是因为首元素就是int*;而&arr加1,后地址增大了16个字节,这是因为&arr去的是整个数组的地址,共有16个字节。
2.当sizeof里面单独一个放数组名,即sizeof(arr),此时数组名表示整个数组,计算的是整个数组大小。
比如:
#include <stdio.h>
int main()
{
int arr[4] = { 1,2,3,4 };
printf("%d",sizeof(arr));
printf("%d",sizeof(&arr[0]));
}
通过程序运算我们发现,在sizeof中arr和首元素地址,计算结果不同,arr是整个数组的大小,而首元素地址,计算出的是首元素的大小。
除了这两种情况,arr都表示首元素地址。
2.使用指针访问数组
有一个数组int arr[4]={1,2,3,4},当我们需要访问数组的元素是,我们可以通过arr[0],arr[1]等方法,同意我们也可以通过指针,进行访问,如:
int arr[4]={1,2,3,4};
int *p=arr;//前面我们讲过arr在这种情况下表示首元素地址;
//如果我们要利用指针访问数组。
*p=10;
*(p+1)=20;
*(p+2)=30;
//我们就可以通过这种方法。
//其中p表示首元素地址,加1和加2分别指向后面元素地址,最后解引用,对地址的空间进行访问。
同理可以推出:*p==arr[0],*(p+1)==arr[1];在这里[]符号表示下标引用和*(+)作用相同,比如:arr[2]也可以写成*(arr+2),arr[0]可以写成*(arr+0)。
3. 一维数组传参本质
一维数组向函数中传参,本质是传的首元素地址,而并非是整个数组的地址。
#include<stdio.h>
void size(int Arr[])//这里的int Arr[]其实是一个指针,可以写成int*Arr形式,它的指针类型是int*,Arr只是首元素地址的临时拷贝。
{
int a=sizeof(Arr);
printf("%d",a);
}
int main()
{
int arr[4]={1,2,3,4};
size(arr);//这里的arr是首元素地址。
}
通过下面代码发现计算出来的是一个元素大小,而并非整个数组的大小。
注意:我们要求数组大小,要在函数外求,然后将求出来的值传入函数中。
总结:函数形参可以写成数组的形式,也可以写成指针形式。
4.二级指针
4.1什么是二级指针
二级指针就是用来存放一级指针的。
其中p虽然是一个指针,它等于a的地址,但是他也是一个变量,有自己的地址,所以我们可以用一个二级指针pp,来指向p的地址,其中pp等于p的地址,同样它也是变量,有自己的地址。
对于int * *pp分析,其中后面的*号,说明pp是一个指针,前面的*和int一起,说明pp指向的是一个int*形 变量。
4.2二级指针的运算
在一级指针中,我们p指向的是a的地址,对p解引用,得到*p等于a。
同理pp是二级指针,其指向的是一级指针的地址,那么对pp解引用,*pp就等于一级指针p。在对p解引用就能得到a,即*p等于a,所以*p=**pp=a。
5.指针数组
这里我们要记住,指针数组,数组在后,所以它是一个数组,是用来存放指针的数组。这里要与数组指针区分来,数组指针,是一个指针,它是指向一个数组的指针。
对于指针数组的学习,我们可以参照前面学习的其他数组,如:
整形数组:int arr[4];
字符数组:char arr[4];
其中int和char是数组的元素类型,arr是数组名,[4]表示的是数组大小。
因此我们要创建一个可以存放4个整形指针的数组,就可以如下:
1.先写出数组类型int* 2.确实数组名 int* arr 3.确定数组大小int* arr[4] 。
6.指针数组模拟二维数组
模拟出二维数组的效果,但不是二维数组。
int arr1[4]={1,2,3,4};
int arr2[4]={5,6,7,8};
int arr3[4]={9,10,11,12};
int arr4[4]={13,14,15,16};
int* arr[4]={arr1,arr2,arr3,arr4};//元素名是首元素地址
这样就可以模拟出一个二维数组,如arr[2][2],arr[2]就等于数组名arr+2,即arr3的地址解引用,此时得到的是数组arr3,在进行arr3 [2], 这一步操作,相当于*(arr3+2),也就是11。
补充:前面我们学过arr[n]==*(arr+n)。
注意上述代码只是模拟出二维数组的效果,并非是二维数组,因为每一个整形数组间的空间并非连续的。