首页 > 编程知识 正文

指针值传递和地址传递,c语言中的值传递和地址传递

时间:2023-05-04 13:30:20 阅读:162557 作者:4272

本文主要介绍了C语言中的传价和指针传递的相关资料。 本文在示例代码中做了非常详细的介绍。 对C语言的学习和使用有一定的参考学习价值。 需要的朋友们如下一起学习吧

前言

我们可能听说过c语言的传值和传指针,其他语言也有传说。 那么,他们到底有什么不同呢? 如果还不能正确分辨,就应该好好了解。

传达价格

我们开始学习c语言的时候被老师教了。 不能用以下方法交换a和b的值。

#包含

voidswap(inta,int b ) )。

{

int temp=a;

a=b;

b=temp;

printf(swapa=%d,b=%dn ),a,b );

}

入主(void ) )。

{

int a=10;

int b=20;

printf(beforeswap:a=%d,b=%dn ',a,b );

swap(a,b );

printf(afterswap:a=%d,b=%dn ),a,b );

返回0;

}

执行结果如下。

before swap:a=10,b=20

内部交换b=10,b=10

after swap:a=10,b=20

可以看出a和b的值最终没有交换。 第一个a、b的值为10、20,最终为相同的值。

为什么呢? 因为函数参数在传递时会传递原始数据的副本。 这意味着,swap内部使用的a和b只是最初始的a和b副本。 因此,在swap函数内部对a和b的任何更改都不会影响初始的a和b值。

因此,我们常说,如果不直接将结构作为参数,效率就会很低。 由于结构本身占用的字节数很大,直接作为参数会生成很大的“副本”,导致效率降低。

结合下图理解吧。

首先,图中上部的a和b表示主函数的a和b,即原始数据,下部的a和b表示函数的自变量a和b,即原始数据的“副本”。 (后面的图都是这样。 上面部分表示原始值,下面部分表示函数参数的值。)。

调用swap函数前后的情况如下:

swap始终只处理a和b的副本,因此完全不影响原始的a和b值。 最终不能达到交换a和b值的目的。

传递指针

那么,我知道为了解决上面的问题,需要传递指针。 代码如下所示。

#包含

voidswap(int*a,int *b ) )。

{

int temp=*a;

*a=*b;

*b=temp;

printf(swapa=%d,b=%dn ),*a,*b );

}

入主(void ) )。

{

int a=10;

int b=20;

printf(beforeswap:a=%d,b=%dn ',a,b );

swap(a,b );

printf(afterswap:a=%d,b=%dn ),a,b );

返回0;

}

执行结果:

before swap:a=10,b=20

swap a=20,b=10

after swap:a=20,b=10

在这种情况下,可以看出a、b的值真的被更换了。

为什么要传递值以及传递指针

看到这里,你可能会怀疑为什么在向函数传递参数时会传递值或传递指针。 为什么传递指针会改变参数的值呢? 其实,在c语言中,参数传递都是传递值! 也就是说,你想的指针也传递值,该值只不过是指针类型。

通过图来理解之前传递指针可以交换a、b值的理由吧:

从图中可以看出,传递给函数的是指向a和b的指针的拷贝,但是因为这个拷贝也同样是指向a和b的,所以虽然不能改变指针的方向,但是可以改变参数a和b所指的内容,也就是原来的a和b的值。

请看转发指针

如果为了指针p而申请内存,以下代码能达到目的吗?

#包含

#包含

虚拟内存(int * p ) )

{

申请1024个int尺寸*

p=malloc(sizeof(int ) *1024 );

if(null==p

)

{

printf("malloc failedn");

p = NULL;

}

}

int main(void)

{

int *p = NULL;

getMemery(p);

printf("address of p is %pn",p);

return 0;

}

通过前面的内容分析,肯定是达不到预期效果的。

运行结果:

address of p is (nil)

这是为什么呢?我们还是利用前面所知来分析,由于传递给getMemory函数的参数都是一个副本,因此函数内的p也是外部p的一个副本,因此即便在函数内部,将p指向了一块新申请的内存,仍然不会改变外面p的值,即p还是指向NULL。

如何修改呢?我们需要传入p的地址,即指向int类型指针的指针。

#include

#include

void getMemery(int **p)

{

/*申请1024个int大小*/

*p = malloc(sizeof(int)*1024);

if(NULL == *p)

{

printf("malloc failedn");

*p = NULL;

}

}

int main(void)

{

int *p = NULL;

getMemery(&p);

printf("address of p is %pn",p);

free(p);

p = NULL;

return 0;

}

运行结果如下:

address of p is 0x144f010

从运行结果可以看到,p的值被改变了。

可配合下面的图进行理解:

总结

本文总结如下:

函数的形参都是原数据的“副本”,因此在函数内无法改变原数据

函数中参数都是传值,传指针本质上也是传值

如果想要改变入参内容,则需要传该入参的地址(指针和引用都是类似的作用),通过解引用修改其指向的内容

以上结论不限于C语言

思考

如何实现不借助第三个变量,交换两个整数的值?

结合本文,理解C++/Java中所谓的传引用

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,

本文作者: 守望

本文链接: https://www.yanbinghu.com/2019/06/20/53981.html

版权声明: 本文为原创文章,版权归守望所有,并采用 CC BY-NC-SA 3.0 许可协议。转载请联系本人!

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。