在学习的过程中,把学到的知识写出来一篇博客,可以帮助我们融会贯通,对知识更了解,记忆更深刻。
1.数组名的理解
数组名通常情况下是首元素的地址,但是有两个例外。
大家可以看这段代码输出的结果,&arr[0],arr,&arr好像输出的都是数组首元素地址,但是当把他们都加一之后,我们发现&arr[0]+1,arr+1,都是跳过了4个字节,而&arr+1却跳过了40个字节,所以我们发现&arr代表的是整个数组,而sizeof(arr)我们发现他计算的是整个数字的大小,单位是字节。由此我们得知:
sizeof(数组名)--这里边的数组名代表的是整个数组。
&arr-这个数组名代表的是整个数组。取出的是整个数组
除了这两个情况外,遇到的数组名都是表示数组首元素地址。
2.使用指针访问数组
我们前边知道,当p指向指针首元素地址之后,那么int*类型指针每次+1,跳过一个整形,也就是说p+0就是arr[0].p+1就是arr[1],然后我们对地址解引用,就可以得到数组的每个元素。p指向首元素的地址,而arr也是代表首元素地址,所以*(p+i)也就等价于*(arr+i)。其实,arr[i]和p[i]的效果是一样的,arr[i]这种写法,编译器也会转换为*(arr+i)这种写法执行。[]是一个操作符,这里先不做讲解。因为[]是一个操作符,所以写成i[arr]也是可以的,但是不推荐,可读性不高。这里只做了解。
3.一维数组传参的本质
数组传参,本质传过去的是首元素的地址。
我们发现,函数里边本意是想求数组元素个数,但是算出来的结果确实1。那这是为什么呢?
原因很简单,前边我们讲过,数组名就是首元素的地址,虽然有两个例外,但是显然,这里表示的就是首元素的地址,所以我们传参,传过去的就是数组首元素的地址,那么sizeof(arr)算出来的就是首元素的字节,然后再除以首元素字节,得到的结果就是1,函数里边的sizeof(arr),因为传过去的是首元素的地址,也就相当于sizeof(arr[o]),所以两者相除得到的结果就是1。所以,数组形参的部分是不会真实创建数组的,传过去的是首元素的地址,那么我们也可以用指针接收。整型数组就可以用整形指针int*p来接收。p是指针名字,可以随便命名。既然传过去的是地址,那么我们在函数里也就求不到他的数组元素个数。如果要在函数里遍历数组的时候,需要把元素个数一起传过去。形参写成数组的方式,主要是为了方便使用。
结论,数组传参传过去的就是首元素的地址。
4.二级指针
pa就是二级指针变量,二级指针变量就是用来存放一级指针变量的地址。也就是说pa里边存放的是p的地址,p里边存放的是a的地址。
如图所示,int*表示p指向的变量类型是int类型,*代表p是指针。那么,int**就可以这样理解,*表示pa是指针,int*是pa指向的变量p的类型。当然也有三级指针就是int***。道理是一样的。
**pa的意思是先对pa进行解引用,就是*pa,得到了p存放的地址,然后再对p进行解引用,就能得到a存放的内容。
5.指针数组
我们知道字符数组就是存放字符的数组,整型数组就是存放整形的数组,顾名思义,指针数组就是存放指针的数组,但是指针有很多类型,比如,int*,char*,double*,那么,我们写指针数组的时候就可以这样:
int* arr[] 这是存放整形指针的数组
char*arr[] 这是存放字符指针的数组
因为存放的地址,所以使用的时候需要解引用。注意,这个arr数组是指针数组,里边存放的是一级指针,所以这个arr数组也就是二级指针。
如果对大家有所助益,这是我的荣幸!