前言:相信大家已经对指针有了初步的认识,那么接下来让我们进入下一章的学习吧!
(这章内容有着比较复杂的一种意义多种形式的东西)
1.数组名的理解
1.1 数组名的理解
我们在之前的学习过程中,遇到过以下代码
通过这个方式拿到数组第一个元素的地址
但是我们都知道数组名本来就是地址,且是数组首元素的地址
我们发现
数组名就是数组首元素(第一个元素)的地址
那么,为了更好的理解,接下来我会直接给出结论,再来分析
数组名就是数组首元素(第一个元素)的地址
但是有两个例外
1. sizeof(数组名):sizeof中单独放数组名,这里的数组名表示整个数组,计算的是整个数组的大小,单位是字节
2. &数组名:这里的数组名表示整个数组,取出的是整个数组的地址(整个数组的地址和数组首元素的地址是有区别的)
1.2 深入区分 arr、&arr
我们看以下代码
仔细观察,我们会发现
1. &arr[0]、arr、&arr 三个打印结果一模一样
2. &arr[0] 和 &arr[0]+1 相差4个字节 , arr 和 arr+1相差4个字节
3. &arr 和&arr+1相差40个字节
为了方便理解,我用一张图区分它们
注意:
尽管它们打印出的地址数值相同,但是&arr仍然是代表整个数组的地址,它们在进行操作时会显现出来不同
2. 指针访问数组
那么,有了前面知识的支持,我们就可以很轻松的访问数组了。
int main() { int arr[10] = { 0 }; //输⼊ int i = 0; int sz = sizeof(arr) / sizeof(arr[0]); //输⼊ int* p = arr; for (i = 0; i < sz; i++) { scanf("%d", p + i); //scanf("%d", arr+i);//也可以这样写 } //输出 for (i = 0; i < sz; i++) { printf("%d ", p[i]); printf("%d ",*(p+i));//同样的可以这样写 } return 0; }
我们会发现,*( p+i )和p[ i ] 是等价的
同理 , arr[ i ] 等价于 *( arr+i ),
3.一维数组传参本质
我们发现好像函数内部并没有正确获得数组的元素个数。
这就要学习数组传参的本质了,上个小节我们学习了:数组名是数组首元素的地址;那么在数组传参 的时候,传递的是数组名,也就是说本质上数组传参本质上传递的是数组首元素的地址。所以函数形参的部分理论上应该使⽤指针变量来接收⾸元素的地址。那么在函数内部我们写sizeof(arr) 计算的是⼀个地址的大小(单位字节)而不是数组的大小(单位字节)。正是因为函数的参数部分是本质是指针,所以在函数内部是没办法求的数组元素个数的。总结:一维数组传参,形参部分可以写成数组的形式,也可以写成指针的形式
4.二级指针
其实理解了一级指针(指针)的本质,二级指针理解起来非常简单:
把一个指针变量的地址存到一个指针里面,那么这个指针就是二级指针
也就是说,*ppa 解引用得到的是pa *paa访问的就是pa
**ppa 先通过 *ppa 找到 pa ,然后对 pa 进行解引用操作: *pa ,那找到的是 a .
5.指针数组
指针数组是指针还是数组呢?
我们类比⼀下,整型数组,是存放整型的数组,字符数组是存放字符的数组。那指针数组呢?是存放指针的数组。指针数组的每个元素是地址,它们又可以指向一块区域
6.指针数组模拟二维数组
这个用的不多,但是我们需要知道这个方法
parr[i] 是访问 parr数组的元素,parr[i] 找到的数组元素指向了整型⼀维数组,parr[i][j] 就是整型⼀维数 组中的元素。上述的代码模拟出二维数组的效果,实际上并非完全是⼆维数组,因为每一行并非是连续的。
总结:是不是感觉指针好像没那么难呀?这说明你已经掌握啦!
作者留言:本人初学者,如有错误或不恰当的地方,欢迎留言指出!
创作时间:2024 .1.4