C语言——深度理解指针(3)
1. 数组名的理解数组名就是数组⾸元素(第⼀个元素)的地址intmain(){intarr[5]{1,2,3,4,5};printf(%p\n,arr[0]);printf(%p\n,arr);return0;}上面的结果可以说明数组名就是数组⾸元素(第⼀个元素)的地址但如果他是下面这种情况呢#includestdio.hintmain(){intarr[10]{1,2,3,4,5,6,7,8,9,10};printf(%d\n,sizeof(arr));return0;}那如果数组名是地址的话那么结果应该是4或者8呀那为什么会是40呢这就不得不说两种特殊情况了sizeof(数组名)sizeof中单独放数组名这⾥的数组名表⽰整个数组计算的是整个数组的⼤⼩单位是字节数组名这⾥的数组名表⽰整个数组取出的是整个数组的地址整个数组的地址和数组⾸元素的地址是有区别的除此之外任何地⽅使⽤数组名数组名都表⽰⾸元素的地址数组名的作用#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;}这⾥我们发现**arr[0]和arr[0]1相差4个字节arr和arr1相差4个字节是因为arr[0] 和 arr 都是⾸元素的地址*1就是跳过⼀个元素。但是**arr 和 arr1相差40个字节这就是因为arr是数组的地址**1 操作是跳过整个数组的2. 使⽤指针访问数组用指针来给数组输入内容,代码如下:#includestdio.hintmain(){intarr[10]{0};inti0;intszsizeof(arr)/sizeof(arr[0]);//输⼊int*parr;//这里的arr代表的就是数组首元素的地址for(i0;isz;i){scanf(%d,pi);//scanf(%d, arri);//也可以这样写}for(i0;isz;i){printf(%d ,*(pi));}return0;}上述代码可知p和arr是等价的所以arr[i]可以被p[i]所替换也可进行数组的访问。同理(p i)等价与p[i] ** ,(p i)等价与(arr i)等价与arr[i]*3. ⼀维数组传参的本质首先我们可以从⼀个问题开始问题我们可以把数组传给⼀个函数后函数内部求数组的元素个数吗代码如下voidtest(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;}那他的结果为什么不一样呢原因是数组传参传递的是数组⾸元素的地址所以在函数test中arr只是代表首元素的地址。总结⼀维数组传参形参的部分可以写成数组的形式也可以写成指针的形式。也就是上面形参中arr[]可以写成arr但本质上还是指针。4. 冒泡排序冒泡排序的核⼼思想就是两两相邻的元素进⾏⽐较如果遇到大小不符合题目要求的话就换一下位置。题目把一组数按升序打印voidbubble_sort(intarr[],intsz)//参数接收数组元素个数{inti0;for(i0;isz-1;i)//有10个元素外循环要进行9次//每进行一次外循环都会把最大数确定出来{intj0;for(j0;jsz-i-1;j)//因为每一次外循环都会确定一个数所以每一次内循环的时候都会依次少一个数比较所以jsz-1-i{if(arr[j]arr[j1]){inttmparr[j];arr[j]arr[j1];arr[j1]tmp;}}}}intmain(){intarr[]{3,1,7,5,8,9,0,2,4,6};for(i0;isz;i){printf(%d ,arr[i]);//打印原来的排列}printf(\n);intszsizeof(arr)//sizeof(arr[0]);//数组元素的个数bubble_sort(arr,sz);//函数传参inti0;for(i0;isz;i){printf(%d ,arr[i]);//打印升序排列}return0;}5. ⼆级指针指针变量也是变量是变量就有地址那指针变量的地址存放在哪⾥这就是⼆级指针#includestdio.hintmain(){inta10;int*paa;int**ppapa;//ppa 就是2级指针用int**来定义return0;}把一级指针的地址放在另外一个指针里面就是二级指针写法就是比一级指针多一个写** *。同理三级指针就是存放二级指针有来定义。对于⼆级指针的运算有1、*ppa* 通过对ppa中的地址进⾏解引⽤这样找到的是pa **ppa* 其实访问的就是pa.intb20;*ppab;//等价于 pa b;2、**ppa先通过 **ppa* 找到pa,然后对pa进⾏解引⽤操作 *pa 那找到的是 a**ppa30;//等价于*pa 30;//等价于a 30;6. 指针数组就是存放指针的数组intmain(){inta10,b12,c13;int*arr[3]{a,b,c};//这就是指针数组printf(%d %d %d\n,*arr[0],*arr[1],*arr[2]);return0;}指针数组的每个元素是地址⼜可以指向⼀块区域7.指针数组模拟⼆维数组示例代码#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] 就是整型⼀维数组中的元素。上述的代码模拟出⼆维数组的效果实际上并⾮完全是⼆维数组因为每⼀⾏并⾮是连续的