C语言基础复盘:指针的深入理解(3)

发布时间:2026/7/18 4:30:53
C语言基础复盘:指针的深入理解(3) 目录前言一、数组名的理解二、使用指针访问数组三、一维数组传参的本质四、冒泡排序五、二级指针六、指针数组使用指针数组模拟一个二维数组前言C语言指针与数组关联紧密本文对数组进行更详细的解释系统地梳理了指针与数组之间的关系。一、数组名的理解数组名就是数组首元素(第一个元素)的地址但是有两个例外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 %p\n,arr);printf(arr %p\n,arr);printf(arr[0]1 %p\n,arr[0]1);printf(arr1 %p\n,arr1);printf(arr1 %p\n,arr1);return0;}运行结果如下这里arr[0]和arr[0]1相差4个字节arr和arr1相差4个字节因为arr[0]和arr都是首元素的地址1就是跳过一个元素。但是arr和arr1相差40个字节这就是因为arr是数组的地址1是跳过整个数组。二、使用指针访问数组我们分别用数组名和指针的方式编写一段代码总结得出arr[i] *(arr i)所以p[i]就等价于*(p i)。实际上这个[ ]就是一个操作符因此我们就可以理解为arr[i]*(arr i)*(i arr)i[arr]1三、一维数组传参的本质#includestdio.hvoidtest(intarr[10]){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]);inti0;printf(sz1 %d\n,sz1);test(arr);return0;}运行结果如下:我们来看这个例子在之前学习一维数组传参时实参传的是一维数组形参写成一维数组但是根据这个结果能推算出传过去的arr占8个字节因此在X64环境下sz2的值为2。这就涉及到数组传参的本质数组在传参的时候数组名表示数组首元素的地址。因为实参传过去的是一个地址所以形参应该拿指针类型来接收看似形参是一个数组其本质是一个指针。因为是一个指针所以在函数内求参数部分的数组的元素个数int sz2 sizeof(arr) / sizeof(arr[0]);这种写法是错误的。既然传的是首元素地址那么能访问整个数组吗当然可以#includestdio.hvoidtest(int*arr,intsz){inti0;for(i0;isz;i){printf(%d ,arr[i]);//arr[i] *(arr i)}}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,sz1);return0;}运行结果如下虽然一维数组传参本质是指针但也可以以arr[i]或*(arr i)的方式访问整个数组。一维数组传参形参的部分可以写成数组也可以写成指针但本质上是指针。四、冒泡排序冒泡排序是排序算法的一种将两两相邻的元素进行比较排序。梳理逻辑1. 确定趟数n个元素 → n-1趟排序2. 一趟内两两相邻的元素进行比较清楚逻辑后开始编写程序//假设我们将数组中的数字通过冒泡排序排成升序#includestdio.hvoidbubble_sort(intarr[],intsz){//趟数inti0;for(i0;isz-1;i){//一趟内的比较intflag1;//假设已经有序intj0;for(j0;jsz-1-i;j){if(arr[j]arr[j1]){inttmparr[j];arr[j]arr[j1];arr[j1]tmp;flag0;}if(flag1){break;//如果一趟本来就有顺序就会直接跳出循环提升运行效率}}}}voidPrint(intarr[],intsz){inti0;for(i0;isz;i){printf(%d ,arr[i]);}}intmain(){inti0;intarr[]{9,8,7,6,5,4,3,2,1,0};intszsizeof(arr)/sizeof(arr[0]);bubble_sort(arr,sz);Print(arr,sz);return0;}}五、二级指针在理解二级指针前先理解一级指针举个例子inta10;int*paa;//pa是指针变量pa是一级指针像pa这样最常见的指针就是一级指针。既然pa是一个指针变量那么变量一定也有自己的地址。int**ppapa;//将pa的地址存起来ppa就是二级指针既然能够通过pa找到a一样也可以通过ppa找到a。#includestdio.hintmain(){inta10;int*paa;int**ppapa;a200;printf(%d\n,**ppa);//200return0;}运行结果如下二级指针变量就是用来存放一级指针的。六、指针数组首先有一个问题指针数组是指针还是数组呢我们运用类比的思想字符数组char arr[5]是用来存放字符的数组整型数组int arr[10]是用来存放整型的数组指针数组char*、int*、float*就是用来存放指针的数组使用指针数组模拟一个二维数组#includestdio.hintmain(){intarr1[]{1,2,3};intarr2[]{4,5,6};intarr3[]{7,8,9};int*arr[]{arr1,arr2,arr3};inti0;for(i0;i3;i){intj0;for(j0;j3;j){printf(%d ,arr[i][j]);}printf(\n);}}运行结果如下这里只是为了方便理解实际编写程序时千万不要写成这种代码*(i arr)、i[arr]。 ↩︎