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

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/haishu_zheng/article/details/82723314

一、二级指针

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

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,显然会出错。


了解小朋友学编程请加QQ307591841(微信与QQ同号),或QQ群581357582。
关注公众号请扫描二维码
qrcode_for_kidscode_258.jpg

猜你喜欢

转载自blog.csdn.net/haishu_zheng/article/details/82723314