深入了解指针(3)
文章目录数组名的理解对arr[i]的理解一维数组传参的本质二级指针指针数组指针数组的用处总结这里是think的博客希望可以一起交流知识一起think今天我们来学习指针(3)吧一起来think吧数组名的理解//测试环境:X86#includestdio.hintmain(){intarr[10]{1,2,3,4,5,6,7,8,9,10};printf(arr[0] %p\n,arr[0]);printf(arr %p\n,arr);return0;}我们发现数组名和数组首元素的地址打印出的结果⼀模一样数组名就是数组首元素(第⼀个元素)的地址。例外sizeof(数组名)sizeof中单独放数组名这里的数组名表示整个数组计算的是整个数组的大小单位是字节。数组名这里的数组名表示整个数组取出的是整个数组的地址。整个数组的地址和数组首元素的地址是有区别的好的这个是常规的讲法那么我把我学习中体会的理解说一下实际上数组名就是整个数组在定义的时候int arr[]{1,2,3};这个时候arr就是整个数组这个时候arr没有退化因为逻辑上没人使用也就不用退化。当sizeof(数组名)数组名的时候这个时候数组名也不退化为什么因为逻辑上这个时候sizeof要的就是数组的大小也要的就是整个数组的地址那么就不用退化。什么时候数组名的意义会从整个数组退化到数组首元素的地址呢下标索引正常单独使用arr等大部分情况那么为什么要退化为了保证逻辑通顺在大多数情况下arr的意义会退化为首元素的地址。举个例子int a arr[i];实际上arr[i]也就是*arriarr是首元素的地址的话是不是刚刚好就可以索引到对应位置找到对应的值了。如果不退化的话你很难去思考怎么利用整个数组这个概念去找到数组中对应的值的所以数组退化为了保证表达式逻辑通顺、语言使用简洁。再举一个例子如果arr不退化为首元素地址的话还是整个数组的话那么arr打印出来是什么显然逻辑上是不清楚的。再来谈谈下一个话题关于arr和arr的区别一个是首元素的地址一个是整个数组的地址他们两个到底有什么区别这就是我上篇博客深入了解指针2所讲到的解引用后可以改变的内存空间有多少指针类型的差别就在±1的步子有多大这些就取决于指针类型这里我们先不谈解引用先来看看±1的步子的差别//测试环境:X86#includestdio.hintmain(){intarr[10]{1,2,3,4,5,6,7,8,9,10};printf(arr[0] %p\n,arr[0]);printf(arr[0]1 %p\n,arr[0]1);printf(arr %p\n,arr);printf(arr1 %p\n,arr1);printf(arr %p\n,arr);printf(arr1 %p\n,arr1);return0;}明显看出首元素地址1跳过4个字节而arr即整个数组地址1跳过40个字节。对arr[i]的理解for(i 0; i sz; i){printf(%d , arr[i]);}for(i 0; i sz; i){printf(%d , *(arri));}return 0;通过这两个for循环可以很明白的看出arr[i]其实就是*(arri)来的。所以其实i[arr]这种形式也是可以的哦只是没有人会这么写。一维数组传参的本质#includestdio.h//测试环境是x86voidtest(intarr[]){intsz2sizeof(arr)/sizeof(arr[0]);printf(sz2 %d\n,sz2);}intmain(){intarr[10]{1,2,3,4,5,6,7,8,9,10};intsz1sizeof(arr)/sizeof(arr[0]);printf(sz1 %d\n,sz1);test(arr);return0;}这里的这个int arr[ ]是函数形参中的其中arr会退化为首元素的地址所以他的实际的形式就是int* arr如果[ ]里面还有数字编译器也是直接忽略的会把它变为int*arr再往下编译。其中因为传参数的时候就是传的首元素的地址所以sz2就是1了地址是4个字节int也是4个字节其中sz1是10是因为arr是数组名定义的时候没有退化移到sizeof中的时候也没有退化所以是sz1是10。而这样的话因为传递的是指针所以函数内部就无法用sizeof来求大小了只能外部传递。二级指针#includestdio.hintmain(){inta10;int*paa;int**ppapa;return0;}**ppa 先通过 *ppa 找到 pa ,然后对 pa 进行解引用操作 *pa 那找到的是a。指针数组指针数组是一个数组一个词的本质是它的最后第一个名词那么指针数组的本质就是数组正如整型数组和字符数组都是数组来类比得到的。指针数组的用处#includestdio.hintmain(){intarr1[]{1,2,3,4,5};intarr2[]{2,3,4,5,6};intarr3[]{3,4,5,6,7};//数组名是数组⾸元素的地址类型是int*的就可以存放在parr数组中int*parr[3]{arr1,arr2,arr3};inti0;intj0;for(i0;i3;i){for(j0;j5;j){printf(%d ,parr[i][j]);}printf(\n);}return0;}parr[i] 是访问 parr 数组的元素 parr[i] 找到的数组元素指向了整型类型的一维数组 parr[i][j] 就是整型类型的一维数组中的元素。上述的代码模拟出二维数组的效果实际上并非完全是二维数组因为每一行并非是连续的。总结谢谢观看