首先我们先通过一题来了解一下实参与形参间值传递的方式。
例题1:
void Getmemory(char *p) { p=(char *)malloc(100); } int main() { char *str=NULL; Getmemory(str); strcpy(str,"hello!"); cout<<str<<endl; }
此题无法正确输出结果“hellow!”。
原因是:在main函数中,首先生成一个指针str指向NULL,然后将str指针传入Getmemory函数。注意!此时在Getmemory函数中的指针p是str的一个副本。即str指向了NULL,p也指向了NULL,但是在Getmemory中执行分配内存的是p指针,str并没有被分配内存!所以接下来的strcpy函数无法正确执行。
那么该如何解决这个问题,使str能够正确分配到内存呢?
方法一:
采用return的方式,将Getmemory运行的结果返还给main函数。
char *Getmemory(char *p) { return p=(char *)malloc(100); } int main() { char *str=NULL; str=Getmemory(str); strcpy(str,"hello!"); cout<<str<<endl; }
我们将分配好内存的p指针返还给main函数,赋值给str指针,所以str也分配好了内存。如果函数体返回的值不止一个怎么办呢?
通过方法一,我们可以提前生成一个结构体,其成员函数是所有要返回的值,return这个结构体就行。
方法二:
采用二级指针的方式,即指针的指针,将p指针的地址p1(1、p指针自身同样占有内存空间,p1指向p 2、地址也是个指针)作为参数传入函数中,生成副本指针p2,p2指针同样指向p指针所在的内存空间,即p2也指向p。在传入的函数中对p2所指向的内容(即p指针)进行更改就可以改变p的赋值。
void Getmemory(char **p) { *p=(char *)malloc(100); } int main() { char *str=NULL; Getmemory(&str); strcpy(str,"hello!"); cout<<str<<endl; }
我们可以发现,将str指针的地址传入Getmemory函数中,生成一个副本指针p,此时p指向的值为str指针。我们的目标是给str指针分配内存空间,所以要对*p(取内容)进行内存分配,而不是对p本身进行内存分配。指针关系如下图所示。
拓展:
对指针的操作分为两部分,一个是对指针自身进行操作,第二个是对指针指向的内容进行操作。
方法三:
在C++中,可以采用引用的方式来处理(C中不可以,没有引用的概念)。将b声明为a的引用,不需要为b另外开辟内存单元,b和a占内存中的同一个存储单元。(int a=1;int &b=a; char *p=NULL; char *&p2=p;)
void Getmemory(char *&p) { p=(char *)malloc(100); } int main() { char *str=NULL; Getmemory(str); strcpy(str,"hello!"); cout<<str<<endl; }
将指针str的引用指针p传入Getmemory中,对指针p的改动同样就是对指针str的改动,p是str的别名。
例题2:
char *Getmemory() { char p[]="hello!"; return p; } int main() { char *str=NULL; str=Getmemory(); cout<<str<<endl; }
此题能否正确打印hello呢?答案是否。这是为什么呢?上文你不是说通过return返回就行了吗?
这是因为,指针p确确实实返回给了str,但是指针p指向的内容“hello!”已经消亡了。在Getmemory函数中数组p为局部变量,其生存周期为函数的执行期间,当函数执行完毕,数组p就消亡了,那么指针p指向的内容就没有了。
那么该如何解决呢?
static。利用static修饰数组p,使其成为静态局部变量,改变它的生存周期,使其生存周期扩展到该CPP运行结束,那么此时str接收到的即为p数组的首地址,数组p也没有消亡,实现打印。
static char p[]="hello!";
例题3:
如果把例题2的 char p[]="hello!";换成 char *p="hello!"; 呢?
答案是可以正常打印。这又是为什么呢?
这是因为,在例题2中“hello!”存储在名为p的数组中,数组p是局部变量,随着函数执行结束消亡。但是在本题中,“hello!”是个字符串,存储在常量区中,我们只是用一个指针p去指向它。return后,指针p消亡了,但字符串仍在常量区中,指针str指向字符串。所以可打印。