ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

深入理解指针(3)学习笔记

深入理解指针(3)学习笔记

一、数组名的理解

数组名就是第一个元素的地址,但是有两个特例
(1)、sizeof(arr[]),这里算的是整个数组的长度,单位为字节。
(2)、&arr。这里注意,对整个数组取地址和对数组中一个元素取地址结果是不一样的:
以十个元素的整型数组为例,如果arr+1,跳过的是一个元素的大小,即四个字节;
如果&arr+1,跳过的是整个数组,即40个字节。
其他情况下,都是首元素的地址。

二、使用指针访问数组

#define_CRT_SECURE_NO_WARNINGS#include<stdio.h>intmain(){intarr[10]={0};int*p=arr;inti=0;intn=sizeof(arr)/sizeof(arr[0]);for(i=0;i<n;i++){*p=i+1;p++;//这里记录一个小错误,第一行需要固定p,让p在一个起始位置上依次加。之前写成*(p+i)=i+1,//这在后面p++的时候起点直接跑偏。}for(i=0;i<n;i++){printf("%d ",arr[i]);//这里写成*(p+i)/i[arr]/(arr+i)都可以,但是第二个写法不推荐。}return0;}

三、一维数组传参的本质

voidtest(intarr[10])......intmain(){intarr[10]={1,2,3,4,5,6,7,8,9,10}test(arr);return0;}

像上述代码,下面的arr传到test中时,从数组变成了指针,即数组降级。
此时在test函数中计算数组的长度得到的是指针变量的长度,4或8;所以需要在main函数中先算出数组的长度。
总结:一维数组传参的时候,形参部分可以写成数组也可以写成指针。因为传参时本质上是在传指针。

四、冒泡排序

核心思想:相邻的两个元素相互比较,排序。

voidbubble(intarr[5],intn){inti=0;//确定趟数for(i=0;i<n;i++){intj=0;intflag=1;//标记第i趟是否有序for(j=0;j<n-i-1;j++)//这里注意j的范围,不要越界访问了。{if(arr[j]>arr[j+1]){flag=0;intm=0;m=arr[j];arr[j]=arr[j+1];arr[j+1]=m;}}if(flag==1)//分清楚赋值符号和判断相等的符号break;}}voidprint(intarr[5],intn){inti=0;for(i=0;i<n;i++){printf("%d ",arr[i]);}}intmain(){intarr[5]={3,5,2,4,1};intn=sizeof(arr)/sizeof(arr[0]);bubble(arr,n);print(arr,n);return0;}

自己写的时候出现了两个小错误,判断相等的符号错写成了赋值符号,还有循环的边界写错了造成了越界访问。
注意,上面代码中有一个提高程序效率的小技巧。定义了flag来标记数组是否已经是升序,如果已经是了,直接跳出循环,减少多余的比较步骤。

五、二级指针

intmain(){inta=0;int*p=&a;//一级指针int**pp=&p;//二级指针return0;}
当然,以此类推,int***ppp=&pp,还可以依次写下去 且解引用后,*pp=p。

六、指针数组

简单理解,数组的每个元素都是指针。

七、指针数组模拟二维数组

通过指针数组,可以把多个一维数组联系在一起,即模拟一个二维数组。

intmain(){intarr1[3]={0,1,2};intarr2[3]={1,2,3};intarr3[3]={2,3,4};int*arr[3]={arr1,arr2,arr3};inti=0;intj=0;for(i=0;i<3;i++){for(j=0;j<3;j++){printf("%d ",arr[i][j]);}printf("\n");}return0;}

打印结果:

返回列表