文章目录
- 一、数组名的理解
- 二、使用指针访问数组
- 三、一维数组传参的本质
- 四、二级指针
- 五、指针数组
- 六、指针数组模拟二维数组
一、数组名的理解
当我们创建一个数组,想要得到数组首元素地址时,就可以使用&arr[0] ,得到数组首元素地址,除此之外,还可以直接使用数组名,因为数组名其实就等于数组首元素地址
测试:
很显然p1和p2的地址是一模一样的,所以数组名就是数组首元素地址
但需要注意的是,数组名等于数组首元素地址有两个例外:
1.sizeof(数组名),当在sizeof()中单独放数组名的时候,这时,数组名不再表示数组首元素地址,而是表示整个数组,因此这里计算的其实是整个数组的大小,并非数组首元素大小
2.&数组名,这里表示的其实是整个数组,取出的是整个数组的地址;在对这样方式取出来的地址进行±整数操作时,也会有所不同
例如:
可以发现,&arr和&arr[0]在进行+1操作时,&arr+1跳过了40个字节,也就是跳过了一整个数组;&arr[0]+1跳过了4个字节,也就是一个元素
除此之外,在其他地方使用数组名就表示数组首元素地址
二、使用指针访问数组
在之前,我们访问数组都是使用的下标访问操作符[ ],在学习指针后,我们还可以使用指针的方式访问数组,首先,创建一个指针变量p,将数组首元素地址存入p当中,然后再对p进行±整数的操作访问数组所有元素
例如:
通过这个代码,我们可以发现,p和数组名arr貌似是等价的,既然arr能通过[ ]访问数组内的元素,
那么p是不是也应该可以呢?
测试一下:
显然,这是可行的
由此,我们可以得出*(p+i) = arr[ i ];同理,arr[ i ] = *(arr+i)
三、一维数组传参的本质
#include<stdio.h>size_ttest(intarr[]){returnsizeof(arr)/sizeof(arr[0]);}intmain(){intarr[10]={1,2,3,4,5,6,7,8,9,10};size_tsz1=sizeof(arr)/sizeof(arr[0]);size_tsz2=test(arr);printf("sz1 = %zu\n",sz1);printf("sz2 = %zu\n",sz2);}运行后发现,在x86的环境下时,sz1 = 10,sz2 = 1;在x64的环境下时,sz1 = 10,sz2 = 2,这是什么原因呢?
其实是因为数组名是数组首元素地址,在数组传参的时候,其实传递的是数组名,也就是说本质上数组传参传递的是数组首元素的地址,函数形参的部分理论上应该使用指针变量来接收首元素地址。所以sizeof(arr)计算的其实是一个指针的大小,这也正是为什么在x86和x64的环境下,sz2的结果不一样。
因此,在函数内部是没有办法求数组的元素个数的
总结:一维数组传参,形参可以写成数组的形式,也可以写成指针的形式
四、二级指针
指针变量也是变量,是变量就有地址,想要存放指针变量,就需要使用到二级指针,同样的,二级指针变量也有地址,存储二级指针变量就需要三级指针变量
二级指针的创建方法:
#include<stdio.h>intmain(){inta=10;int*pa=&a;int**ppa=&pa;printf("pa = %p\n",pa);printf("ppa = %p\n",ppa);}这里的ppa就是二级指针,ppa存放的就是指针变量pa的地址,ppa的类型就是int* 类型
当我们需要访问a的内容的时候,就需要使用两次解引用操作*(*(ppa)),*ppa解引用后就是pa,pa再解引用就指向了a
五、指针数组
指针数组就是存放指针的数组
创建方式:
#include<stdio.h>intmain(){inta=10;intb=20;intc=30;int*parr[]={&a,&b,&c};inti=0;for(i=0;i<3;i++){printf("%d ",*parr[i]);}}这样就成功创建了一个指针数组,指针数组中的每一个元素都是一个指针,想要访问该指针指向的内容就需要进行解引用操作
六、指针数组模拟二维数组
#include<stdio.h>intmain(){intarr1[5]={1,3,5,7,9};intarr2[5]={2,4,6,8,10};intarr3[5]={1,2,3,4,5};int*parr[]={arr1,arr2,arr3};for(inti=0;i<3;i++){for(intj=0;j<5;j++){printf("%d ",parr[i][j]);}printf("\n");}}parr[ i ]就是访问parr数组的元素,parr[ i ]找到的数组元素指向了一维数组,parr[ i ][ j ]就是访问指向的一维数组当中的元素
需要注意的是,上面的代码只是模拟出二维数组的效果,并不是真正意义上的二维数组,因为每一行并非是连续的
完