指针的概念理解和知识点梳理

数组名的含义

数组名在三种情况下有不同的含义:

1、sizeof(arr)其中的数组名arr,表示的是整个数组元素的大小

2、&arr,在这种情况下,arr表示的是整个数组的地址

3、除去以上的俩中情况下,其它的数组名,都表示数组首元素的地址

指针

指针是来存放内存中的地址的.

指针个人认为可以分为三大类:一级指针、二级指针和野指针

一级指针又可以分为指针变量和指针数组

指针变量分为指针变量、数组指针、函数指针和void型的指针

指针数组分为指针数组和函数指针数组

指针的解引用和+-整数

指针的解引用和+-在指针的运用上是必不可少的。解引用和+-整数都会与指针的类型相关。

解引用操作符

解引用操作符是访问字节(字节数与类型相关),并进行修改

如:

其中int类型为4个字节,在int*中*p就表示能够访问所指向的对象(n)的4个字节的内容。*p取得4个字节就是为整一个n的内容。其中*p=0,就表示n被赋值为0。还有一个情况为:

其中把n的地址强制转化为char*的类型。在char*中char就表示把能够访问所指向的对象(n)当作为char类型,char为一个字节。在char*中条件中*p就表示能够访问所指向的对象(n)的1个字节的内容,被赋值的也只有一个字节的内容。

在实际中对于第二中情况的较少,所以我们一般会习惯的把*p直接等价于n,也就是第一种情况。

指针+-整数

指针的+-整数是能够跳过几个元素(本质是字节),与解引用相类似

如:

(&n应为int*类型的)其中强制转化为char*类型的p1。在char*中char就表示把p1所指向的对象(n)当作为char类型,char为一个字节。p1和p1+1的地址相差1(一个字节),说明了p1+1跳过了一个字节。同理,int*类型的,int为4个字节,就跳过4个字节。

一级指针

指针变量

指针变量

指针的形式主要为(类型)*  变量名,其中的类型可以为int、char和int*等等一些类型。比如int * pa1、char* pa2。假设一个指针为int* p。  其中的*表示的是p是一个指针变量,int表示的是p变量里的地址为指向的对象的类型是为int类型。同理,假设一个指针为int* * p(二级指针),其中的第二个*表示的是p是一个指针变量,int*表示的是p变量里的地址,这个地址所指向的对象的类型为int*类型。

比如:p中所存放的地址为变量n的地址,int*中的int就是表示p中的地址所指向的对象(n)的类型为int。

数组指针

数组指针是一个指针而不是数组,指针里面存放的是整一个数组的地址。而取整个数组的地址就需要用到取地址&。如:

 

其中的pa就是数组指针变量,存放的是arr整个数组的地址。其中的pa为变量名而*与pa是先结合的,就表明pa是个指针而不是一个数组,而[10]是表示所指向的数组大小是10,int

数组指针的+-整数

数组指针的+-是跳过一整个数组,因为数组指针的类型是int(*)[10]所对应的是一个数组,一个有10个元素且每个元素的类型都为int的数组,整个arr数组所占的字节就为40(整个数组)。所以跳过的就是整个数组。我也可以类比一下int* p的指针,p类型是为int*,跳过的是4个字节(int)。

补充比较特殊的与数组指针有点关系的:二维数组

二维数组的本质是由一维数组组成,我们可以把一维数组当作为一个元素,而由多个元素(一维数组)组合而成的数组就是为二维数组。

所以&arr(二维数组)取得是整个二维数组的地址,arr取得是首元素的地址,在二维数组中取的arr1整个数组的大小。

函数指针

可以类比数组指针,存放数组地址的指针,为数组指针

那么函数指针,存放的函数地址的指针,为函数指针。那么我们要怎么得到函数的地址,函数名就表示的函数的地址,也可以用&+函数名来表示。函数指针是什么样,假定一个函数指针为int(*pa)(int x,int y)。其中pa为变量名,*是与pa先结合的表示pa是指针变量,而不是数组;int表示的是指针变量所指向的那个函数的返回类型;(int x,int y)表示的是指针变量所指向的那个函数的函数参数

对于函数指针的运用:以上面的int(*pa)(int x,int y)为例,*pa(实参,实参),其中的*可以不用加

void*指针

void型的指针形式为void*变量名,是为泛型指针,void*指针可以接受任何类型的地址。但是void*指针也有局限性,不能对指针变量做任何的解引用操作和+-整数,因为可以接受任何类型的地址,对其解引用操作时不知道时访问几个字节的内容(1字节?4个字节?),同理+-整数是一样的不知道是跳过几个字节。

所以void*指针常与const连用

const

const修饰指针,让其不能对指针进行解引用操作,const的运用以int* p为例:const int* p或者int const* p都是不能*p操作的也就是不能通过p对其所指向的对象进行重新赋值;int* const p是不能修改p变量的值

指针数组
指针数组

指针数组的形式为   类型*数组名[ ],我们假定一个指针数组int* pa[10]。其中的数组名pa和[10]先结合,没有与*先结合也就是这样的形式(*pa),就表明了pa是一个数组,那它是一个什么样的数组。我们可以用一般的数组来类比了解

             int arr[10],数组名为arr,数组的大小为10个元素,每个元素的类型为int,是个整数数组,存放整形的数组

那么就可以类比:  int* pa[10],  数组名为pa,数组的大小为10个元素,每个元素的类型为int*,是个指针数组,存放指针的数组。没错指针数组是来存放地址的数组

函数指针数组

与上面的指针数组相类似,函数指针数组的形式为  类型(*数组名[ ])(实参,实参),我们同样先假定一个函数指针数组int (*pa1[10])(int x,int y),pa1也是先与[ ]结合,所以是个数组,按照同样的类比方法来了解以下定义:

 int arr[10],数组名为arr,数组的大小为10个元素,每个元素的类型为int,是个整数数组,存放整形的数组

int (*pa1[10])(int x,int y),数组名为pa1,数组的大小为10个元素,每个元素的类型为int  (*[10])(int x,int y)(去掉变量名就为类型),是个函数指针数组,存放的就是函数指针的数组喽。

二级指针

指针变量也是变量,是变量就会有地址。那么存放指针变量(一级指针)的地址就是二级指针。

如:

其中的p就是为二级指针变量,其中的第二个 * 表示p是一个指针变量(二级指针),它的类型就是为int*

野指针

概念

:野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)。

(越界访问)

成因

指针未初始化

变量未初始化时编译器就会自动给你初始化一个随机值,而给的随机值也就是内存中的地址,而如果,给的随机值没有在编译器给你开辟的地址范围里,对其访问时(越界访问),就有可能为野指针。

指针的越界访问

当i=5时,第六次循环,对p进行解引用时,这个p就时野指针(数组越界

指针指向的空间释放

这个情况主要出现在调用函数时,如:

其中n是在函数里创建的变量,出函数时这块空间就会还给系统,这块空间就不属于我们了,所以我们再对其解引用操作时就会造成越界访问

如何规避野指针

指针初始化、小心数组越界和没有具体地址时,给它赋值NULL。NULL是空指针,值为0;但在使用时要注意,不能对赋值为空指针的指针做解引用操作,如果读写了编译器会报错。

最后,其中有什么遗漏或错误的地方,希望大家能够帮我指出,感谢。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值