对实参与形参之间数据传输的一些理解(指针指向、存储位置)

首先我们先通过一题来了解一下实参与形参间值传递的方式。

例题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指向字符串。所以可打印。


猜你喜欢

转载自blog.csdn.net/weixin_41710905/article/details/79576636