一、一级指针
什么是一级指针:所有普通变量的地址都是一级指针,存放一级指针的变量就是一级指针变量。
什么是普通变量:在定义过程中,类型没有*号的变量就是普通变量。
二、一级指针类型
1、类型结构
普通变量的类型+*
char a = 'a'; char *p = &a; //char * = char + *
讯享网
&a的类型为char *,放&a的变量p自然也是char *。=两边是天然一致的,不一致就需要强制类型转换。
2、如何理解(char *)
- char:指针指向空间的解释方式。
- *:表示它是一个指针。
3、a / &a / p / *p / &p各自的含义
讯享网char a = 'a'; char *p = &a;
- a:char的普通变量
- &a:a的指针,类型为char*
- p:char*指针变量
- *p:p中指针所指向的空间
- p为char*,*p解引用的时候,抵消了一个*,char就是p指向空间的解释方式。
- &p:变量p的指针。类型为char
三、多级指针
什么是多级指针?
:指针变量的指针就是多级指针,指针变量也是变量,所以指针变量的每个字节也是有地址的,那么“指针变量”第一个字节的地址就是多级指针。
在多级指针的类型中,*的个数代表了指针的级数,n个*就是n级。
例如:一级指针变量的指针就是二级指针,存放二级指针的变量就是二级指针变量。
1、类型结构
二级指针的类型结构为,一级指针类型 + *,比如:
int a = 100; int *p1 = &a; int p2 = &p1; //int = int * + *
&p1的类型是int,存放&p1的变量p2自然也是int。
2、如何理解( int )
int 解读:
- int*:指针指向空间的解释方式。
· *:最后一个*代表它是指针。
3、各自的含义
a / p1 / *p1 / &p1 / p2 / *p2 / p2 / &p2
讯享网int a = 100; int *p1 = &a; int p2 = &p1;
a:int变量p1:int *指针变量,用于存放int *的指针*p1:p1中指针所指向的空间
p1为int *,*p1解引用时,抵消一个*,解释方式为int&p1:一级指针变量p1的指针,为int的二级指针p2:int指针变量,用于存放int的二级指针*p2:一级解引用,代表的是p2中指针所指向的空间,p2为int,解引用时,抵消一个*,解释方式为int *p2:二级解引用,代表p2所指向的p1所指向的空间,这里就是a的空间
如果需要一个等价代换的话:
p2——————>*(*p2)——————>*p1 ————————>a
&p2:二级指针变量p2的指针,类型为int *
再例如下面这个情况:
讯享网int a = 100; int *p1 = &a; float p2 = (float )&p1;
*p2:按照float*解释p1
*p2 ——————> (float *)p1
p2:按照float解释a
讯享网p2 ————> *(*p2) -----> *((float *)p1) ——————> (float)a
四、一级指针和多级指针的异同
1、相同
不管是几级指针,都是一个地址,所有地址宽度都是一样的。
既然指针的宽度都是一样的,那么放指针的“指针变量”的宽度的也全都是一样的,不管它是多少级的指针变量。
2、不同
不同之处在于解引用的深度。
一级指针:解引用深度为1级
二级指针:解引用深度为2级
三级指针:解引用深度为3级
….
3、不同级别之间强制类型转换
不同级别之间的强制转换,改变的是解引用的深度。
1)例子1
int a = 10; int *p = &a; //&a为int *
解引用深度:*p为1级,抵消了一个*,按照int去解释所指向的a空间。
讯享网int a = 10; int p = (int )&a; // &a为int *
解引用深度变为了2级:*p:抵消一个*,按照int *去解释所指向的a空间
p:抵消两个,按照int去解释a的10所指向的空间
p --> *(*p) ---> *(a) ———> *10 // 非法操作
事实上10根本不是一个有效的地址,10并没有对应有效存储空间,就算有对应空间,
也是一个不明情况的非法空间,所以不能以指针的方式去解引用10,强行解引用的话,就会导致指针错误。
2)例子2
讯享网int a = 10; int *p = &a; int *p1 = (int *)&p; //&p为int
解引用深度变为1级
*p1:抵消了一个*之后,以int方式解引用p1所指向p空间,将p中的指针&a强行解释为一个整形数。
*p1 ——————>(int)p ————————>(int)&a
p1:无法编译通过
讯享网p1 ---> *(*p1) ——————>*((int)p) ————————> *((int)&a) ——————> *(整形)
从以上等价后的结果可以看出,*(整形)在尝试对一个整形数进行解引用,这是无法编译通过的。
我们前面说过,同一个数但是类型不同,会有很大区别,当编译器检测到你对一个整形数进行解引用时,会直接报类型错误,提示你,你在尝试解引用一个整形数
如果你非要当做整形的数来用,必须做强制转换。
((int )p1) ----> *(&a) ——————*(int *指针)
五、总结
- 要么指针指向的空间不存在,比如前面例子中
10,将10当做指针使用是不行的,因为不指向任何有效空间 - 要么指针类型不匹配,不允许进行解引用
对指针进行解引用时,一定要确保指针为合法指针,不合法情况有如下几种:
(1)类型不正确,解引用的根本就不是指针:*(整数) 像这种情况,直接会导致编译不通过
(2)指针所指向的空间压根就没有:指针的类型对的,但是指针没有对应任何空间。所以对这种指针进行解引用时,会导致指针错误,压根找不到空间,像这种情况,编译没问题,但是运行时会有指针错误
3)指针类型没问题,也有对应实际的存储空间,但是没有访问权限:
- 1)这不是你应该访问的空间
- 2)人家只允许读,你偏要写
像这种情况,编译也没问题,但是运行会有指针错误。
非法指针举例
1)一级指针
讯享网int *p1; int fun(void) { int *p2; *p1 = 100; *p2 = 200; }
*p1=100和*p2=100都有问题。
首先p1是全局变量,p1会被自动初始化为0,也就是说p1中的地址默认为0,但是0地址是没有对应实际内存空间的。
p2是fun函数内部的自动局部变量,自动局部变量栈在未初始化的时候为随机值,这个随机值会有问题:
1)问题1:如果这个随机值没有对应任何空间的话,*p解引用访问时的会导致指针错误,然后程序会被终止
2)问题2:如果恰好有对应某个空间,如果这个空间不允许写访问的话还好,因为这会直接导致指针错误,程序被终止,程序员就回去排查错误。
允许写的话更糟糕,因为这个空间很可能是其它变量的空间,这会导致数据的篡改,所以对指针进行解引用时,指针必须是合法的,只有这样才能访问正确的空间。
下面是代码的改进:
int a = 0; int *p1 = &a; int *p2; p2 = malloc(4);
2)多级指针
讯享网int *p1; int p2 = &p1; int fun(void) { p2 = 100; }
*p2 —> p1 一级解引用是正确的,二级解引用是指针错误。
改进:
int a = 0; int *p1 = &a; int p2 = &p1;

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/37466.html