一级指针
先解释一下什么是指针,为什么要有指针
指针:
在计算机科学中,指针(Pointer)是编程语言中的一个对象,利用地址,它的值直接指向(points to)存在电脑存储器
中另一个地方的值。由于通过地址能找到所需的变量单元,可以说,地址指向该变量单元。因此,将地址形象化的称为“指针”
意思是通过它能找到以它为地址的内存单元。(百度百科)
我们可以这样理解:指针是一个变量,是用来存放某块地址的变量
为什么要有指针?
我们只要计算机要将程序运行起来就要将程序加载到内存。为了很好的管理内存,将计算机的内存分成很多小的单元,
每个单元都对应一个独一无二的地址,这样就一个地址标识一块空间。
指针让地址有地方存放,指针让内存的访问更加方便
一级指针即指针,其存放的是普通内置变量的地址
代码总结如下:
当我们创建变量i时,会在内存中为i分配一块内存空间,&i取出变量的地址(&取值操作符),p为指针变
量(即存放地址的变量)。
我们知道变量有不同的类型,当然指针变量也是有类型的,那指针都是存放地址,为什么还要区分不同的类型呢?这里就涉及到指针+-整数和指针的解引用 ,这里就不做过多的测试,总结如下:
指针的类型决定了指针向前或者向后走一步有多大(距离) 指针的类型决定了,对指针解引用的时候有多大的权限(能操作几个字节)
二级指针
指针的本质就是地址
二级指针就是指向一级指针的指针(n 级指针就是 指向 n-1 级指针的 指针)
在上面代码中,a的地址存放在pa中,pa的地址存放在ppa中,即pa为一级指针,ppa为二级指针
对于二级指针的运算:
*ppa通过对ppa中的地址进行解引用,这样找到的是pa ,*ppa 其实访问的就是pa .
**ppa 先通过*ppa 找到pa ,然后对pa 进行解引用操作:*pa ,那找到的是a .
一维数组、二维数组
前面有篇解析数组的博客中详细的介绍了一维数组与二维数组,这里不再描述
点击打开链接
指针和数组的关系
1.数组的引用被转化为指针加偏移量的引用
2..在函数形参中的表现
在向函数传递参数时,如果实参是一个一维数组,那用于接受的形参为对应的指针,也就是传递过去是数
组的首地址而不是整个数组。如果实参是一个二数组,可以用数组指针进行传参,可见下面对数组指针的分析
数组和指针没有必然的联系,数组是相同元素的集合(可以通过下标方式或指针方式进行访问)。
指针是存放的是变量的地址。指针是一类特殊的变量,主要用途是函数间的传址,用这种方式来改变实参内容。
而数组是用来实现线性表的结构,用于把同类对象集中在一起放置。
指针数组
我们对指针有了了解,也对数组有了了解,那指针数组是指针还是数组呢?
指针数组是数组,是一个存放指针的数组
一个存放int类型的数组称为整型数组,那么存放指针的数组就叫指针数组。
eg:
数组指针
数组指针是一个指针,这个指针有能力指向数组(指向数组的指针)
eg:int (*p)[10];
//解释:p先和*结合,说明p是一个指针变量,然后指着指向的是一个大小为10个整型的数组。所以p是一个
指针,指向一个数组,叫数组指针。
//这里要注意:[]的优先级要高于*号的,所以必须加上()来保证p先和*结合。
数组的地址如何存储呢?
int arr[10] = {0}; int (*ptr)[10] = &arr;
ptr是数组指针,所以存放数组的地址比较合适
我们要将二维数组传参,应该怎么办?
//测试 void test() { int arr[3][5] = {0}; print(arr);//这里print函数的参数如何设计? }
//下面三种为二维数组传参时,参数的设计 void print(intarr[3][5]) {} void print(intarr[][5]) {}
voidprint(int(*arr)[5]) {}
与指针数组的区别:
数组指针是指向数组首元素的地址的指针,其本质为指针
指针数组是数组元素为指针的数组,其本质为数组。
函数指针
函数指针是指向函数的指针变量。 因而“函数指针”本身首先应是指针变量,只不过该指针变量指向函数。
这正如用指针变量可指向整型变量、字符型、数组一样,这里是指向函数。
看下面代码:
由上面结果可以看出:这两个是test函数的地址
那我们如何保存函数的地址呢?
首先要储存地址,应该是个指针,指针指向的是一个函数,指向的函数无参数,返回值类型为void。 所以应该用void (*pfun1)();来存放test函数的地址。