函数传参
2017-11-21 13:28 小白很我 阅读(181) 评论(0) 编辑 收藏 举报#include<stdio.h> viod get_memory( char** p) { *p = "hello world." } int main ( int argc, char* agrv[] ) { char* str = NULL; get_memory ( &str );
printf ( “%s\n”, str ); }
输出: hello world.
清楚一点,str和 形参p都在栈内存中,但是实参str和形参p在栈内存空间是完全独立的。get_memory( &str )调用时,将&str传递给了形参p,这样形参和实参就没有半毛钱
关系了。
被调函数就获得了传递过来的内容,存放在栈空间的形参变量中,传递过来的东西最常见的有两种,一种是数值,一种是地址。所以就有什么值传递和引用传递之说。
其实函数不会管那么多的,传什么装什么,装什么用什么。
形参也是变量,也有类型。函数调用时,要根据形参类型给形参分配一块栈内存。将来有人将一些东西装到这块内存中,然后被调函数就拿这些东西用就行了,像使用
普通变量一样去使用形参变量。只不过使用不同的传进来的东西,造成的后果不一样。
传数值,形参变量(栈内存)装数值,使用形参变量就是使用数值,给形参赋值就是给形参的栈内存赋值。
传的是地址,形参变量(栈内存)装地址。使用*(address)时,你就能访问和修改该地址对应的内存,这就是地址本身的用法,无论在哪都这么用。结果是改变了外部的内存的内容,就是这一点很神奇,导致了我们很迷惑。
一定要对 void func(char** p)有感觉。
1)形式参数也是变量,char** p也算半个定义,那么你分析一下形参变量内存大小,什么类型?
a)谁是形参?
是p是形参,还是*p还是**p是形参?当然是p。类比一下char* *ptr;定义,ptr才是变量,不是*ptr和**ptr。所以p是形参。
b)p是什么类型?
我们char**str;str的类型?
拿掉str就是str的类型了,也就是说是char**。我能使用*(解引用)那么我是指针,拿一个*出来,即*p(解引用,指向)指向char*,翻译出来就是,我是指针,我是指向char*的指针。所以我们得到了形参的数据类型吧,指向char*的指针。
c)分配多大栈内存?
既然是指针就分配8个字节咯(64gcc)。
主调函数给被调函数对应的参数,传来的东西装到形参中,那就没你主调函数什么事了,我操作我的我。改变了外部的内存,也是你把那块内存的地址给我了我才改的。
奇葩幻想:
char **p;一看到这个东西你就得想到背后有3块内存存在。p是变量要一块p=address1; *p=*(address1)=address2是一块;**p=*(address2)=char又是一块。你要搞明白你在操作哪一块内存。
p = address1;你在操作第一块内存,指针变量p;*p=*(address) = ??;你在操作第二块内存;**p=*(address2) = ??;你在操作第三块内存。我这里是将最内层的内存(变量p)的内存当第一块内存的。
函数传递指针我们经常看到*p 操作,明显是在操作第二块内存。对于形参是char** p时,使用*p明显是在修改address2即char*。最上面的例题*p =“hello world”;就是把hello
world的首元素地址赋值给*p,p里面转的是str的地址,*p不就是str变量本身的那块内存吗。那结果就是str 等于“hello world”的首地址,其实这个函数的效果和str=“hello world”
等价。