C语言函数传指针时究竟传的是什么?

C语言函数传指针时究竟传的是什么?

我们知道指针指中的内容是一个内存的地址,只有对指针进行解引用(*p),计算机才会指针所指向地址中的内容。在进行函数间调用时传递指针经常会造成段错误(也就是内存错误),其实主要是空指针引起的,或者指向了错误的位置。首先看如下一段代码

#include <stdio.h>
#include <stdlib.h>
void init(int *p);

int main(void)
{
        int *ptr;

        init(ptr);
        printf("%d", *ptr);

        return 0;
}

void init(int *p)
{
        p = malloc(sizeof(int));
        *p = 1;
}

这段代码的内容很容易理解,首先在mian函数中定义一个变量ptr,其次通过init函数分配一个堆上的int,将其值设置为1,把ptr指向这个堆上的int。实际运行一下就会发现报错。

运行结果

原因是什么呢?因为ptr并没有指到堆上的内存,是一个空指针!!!堆上分配的内存早已泄露。将代码稍作修改,我们将各个指针的指向的地址打印出来看一看。

#include <stdio.h>
#include <stdlib.h>
void init(int *p);

int main(void)
{
        int *ptr;

        printf("初始化之前 ptr = %p\n", ptr);
        init(ptr);
        printf("初始化之后 ptr = %p\n", ptr);
        printf("%d\n", *ptr);

        return 0;
}

void init(int *p)
{
        printf("赋值之前 p = %p\n", p);
        p = malloc(sizeof(int));
        *p = 1;
        printf("复制之后 p =  %p\n", p);
}

运行可以得到如下结果

这里写图片描述

我们看到ptr并未被修改,一直是空指针;尽管在init函数内指针的修改是成功的。我们看如下的图来说明。

这里写图片描述

上图中蓝色线代表各个指针指向的位置,红色线代表随着程序的执行,指针内容的变化。函数调用传递的其实是一个值的复制,所以传指针时也是将指针变量中指向的地址传递过来。当开始调用init函数时,系统把ptr指向的地址传递过来,所以p=ptr=null;之后我们用malloc分配了堆上的内存,并将p指向了这个内存,所以p=0x1234567;最后我们将0x1234567这个地址中的值通过指针操作设置为1,*p=1。从这个过程中我们可以看到ptr一直指向null,从未改变过,尽管p=ptr,但这只是将p和ptr指向了同一个位置,无法对ptr指针的内容进行修改。为了修改ptr,需要将p指向ptr,所以正确的应该为p=&ptr才可以,这样就可以利用指针p对ptr进行操作。这样整个操作如下图所示。
这里写图片描述
只有通过将p指向ptr,才能对ptr中的内容进行修改。开始时ptr指向null,后来p将ptr指向的内容改到0x1234567上,并将其值设为1。修改代码如下:

#include <stdio.h>
#include <stdlib.h>
void init(int **p);

int main(void)
{
        int *ptr;

        init(&ptr);
        printf("*ptr = %d\n", *ptr);

        return 0;
}

void init(int **p)
{
        *p = malloc(sizeof(int));
        **p = 1;
}

运行得到正确结果
这里写图片描述

可以把各个指针指向的地址打印出来看一看

这里写图片描述

可以看到p=&ptr,p指向ptr,所以可以通过p对ptr进行任何操作;*p=ptr对ptr指向的地址进行了修改,最后通过**p=*ptr=1将0x55cf352e9420地址中的值设置为1

无论参变量是什么,函数传递其实是将形参中值复制过去,指针同样也是将指针中的值复制过去,并不是把指针拷贝过去。所以不要被交换两个数值可以用指针这种方式迷惑,误以为是把指针拷贝过去了。只要记住函数传递是形参值的拷贝,无论嵌套多少指针(例如int *****p)都不会被迷惑。

指针是C的精髓,非常的灵活,可以直接对内存做修改,也是C语言的强大之处,所以学C的同学一定要掌握指针哦!!!

  • 18
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值