为了账号安全,请及时绑定邮箱和手机立即绑定

小朋友学C语言(41):二级指针与多级指针

标签:
C++

一、二级指针

指向指针的指针是一种多级间接寻址的形式,或者说是一个指针链。通常,一个指针包含一个变量的地址。当我们定义一个指向指针的指针时,第一个指针包含了第二个指针的地址,第二个指针指向包含实际值的位置。

webp

1.jpg

一个指向指针的指针变量必须如下声明,即在变量名前放置两个星号。例如,下面声明了一个指向 int 类型指针的指针:

int **p;

当一个目标值被一个指针间接指向到另一个指针时,访问这个值需要使用两个星号运算符,如下面实例所示。

例1:

#include <stdio.h>int main (){    int a;    int *ptr;    int **pptr;

    a = 100;    /* 获取 a 的地址 */
    ptr = &a;    /* 使用运算符 & 获取 ptr 的地址 */
    pptr = &ptr;    /* 使用 pptr 获取值 */
    printf("a = %d\n", a);    printf("*ptr = %d\n", *ptr );    printf("**pptr = %d\n", **pptr);    return 0;
}

运行结果:

a = 100
*ptr = 100
**pptr = 100

可以进一步查看一下指针的地址。

例2:

#include <stdio.h>int main(){    int a = 5;    int *ptr = &a;    int **ptr2 = &ptr;printf("%d,%d,%d\n", **ptr2, *ptr, a);printf("%p, %p, %p\n", *ptr2, ptr, &a);    printf("%p, %p\n", ptr2, &ptr);    printf("%p\n", &ptr2);    return 0;
}

运行结果:

5,5,5
0061ff0c, 0061ff0c, 0061ff0c
0061ff08, 0061ff08
0061ff04

从结果可以看出,**ptr2, ptr, 指向了a的值。一级指针ptr2和ptr则指向了a的地址。二级指针ptr2指向了一级指针ptr的地址, ptr2本身的地址则是0x0061ff04。

二、多级指针

既然有一级指针和二级指针,就有三级指针、四级指针、五级指针……
以三级指针为例,三级指针是“指针的指针的指针”,或者叫“指向‘指向指针的指针’的指针”。
因为多级指针不好理解,并且在编程时容易写错,所以建议尽量不要使用二级以上的指针。

三、指针指向NULL

经常看到给一级指针赋值为NULL的程序。比如下面的程序。

例3:

#include <stdio.h>int main(){    int a = 5;    int *p = NULL;
    p = &a;    printf("%p,%p,%p,%d", &p, p, &a, *p);    return 0;
}

运行结果为:

0061ff08,0061ff0c,0061ff0c,5

这里定义了指针后,把指针指向NULL。这是一种安全的写法。NULL值为0,被放在内存里地址为0x0的区域。这是一块安全的内存区域。程序里p先指向了这块安全区域,然后再指向变量a的地址。
最后打印出来结果可以看出,p本身的地址为0061ff08;p所指向的地址即a的地址为0061ff0c;*p为a的值,即5。

字符’\0’的值也是0。
虽然值都是0,但意义不一样:
(1)0表示数字
(2)‘\0’表示字符串结束符。
(3)NULL表示空对象或空指针。

四、NULL内存区域不可读写

0x0这块内存区域是不可写的。NULL这个值在一些编译器连读取都不能。

下面用Codeblocks集成开发环境测试一下。

例4:

#include <stdio.h>int main(){    int *p = NULL;    printf("%p, %p\n", &p, &(*p));    printf("%d\n", *p);    return 0;
}

运行结果:

0x6dfefc 00000000
Process returned -1073741819 (0xC0000005)

从运行结果可以看到,打印出了p指针本身的地址,为0x6dfefc;也打印出了NULL所在的地址00000000。但是,没有打印出p,而是报”Process returned -1073741819 (0xC0000005)”的错误。这里p就是NULL或0。可见在Codeblocks开发环境里NULL内存不能读取。

再看看二级指针的情况。

例5:

1 #include <stdio.h>2 3 int main()4 {5     int a = 5;6     int *ptr = &a;7     int **ptr2 = NULL;8     9     *ptr2 = ptr;10 11     printf("run ok\n");12 13     return 0;14 }

这个程序运行时报错。下面来分析一下原因:
第6行定义了一个1级指针ptr,接下来的程序里若出现ptr表示指针所指向的地址里的值。即ptr是一个1级指针,ptr是一个整数值。
第7行定义了一个2级指针ptr2,接下来的程序里若出现ptr2表示ptr2所指向的一级指针的地址,若出现ptr2表示2级指针ptr2所指向的一级指针指向的地址里的值。简单地说就是ptr2是一个二级指针,ptr2是一级指针,ptr2是一个整数值。
第9行
ptr2 = ptr,表示一级指针指向一级指针,逻辑上没有问题。那么为什么会错呢?
原因在于第7行的ptr2 = NULL,这表示ptr2指向的地址为0x0,即
ptr2 = 0x0。0x0是一个特殊的内存块,不能读写,要对他赋值*ptr2 = ptr,显然会出错。



作者:海天一树X
链接:https://www.jianshu.com/p/2b0cfdd02dd6


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消