指针作为行参

关于指针作为函数参数的一点研究

事情大概起源于这样一个问题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include<stdio.h>
void Try_change( int *p)
{
         int b=7;
         p=&b;
}
int main()
{
         int *p=NULL;
         int a=5;
         p=&a;
         Try_change(p);
         printf ( "%d\n" ,*p);
         return 0;
}

 

当我第一次看到这个题目的时候我觉得答案是7,但是又好像是5,模模糊糊,傻傻分不清楚,这也是我想深入探究下这个问题的原因。

如果你一眼知道答案并且知道为什么,希望不吝指教。

 

首先这是一个指针作为函数变量的问题,之所以会对此类问题模糊,是因为对指针在参数传递过程中的流程不是很清楚。

我最初的思路:

主函数定义一个指针------------通过函数调用将此指针传递到Try_change中------------在Try_change中改变指针的指向--------------回到主函数输出该指针的值

由于我看到在Try_change 中改变了指针的指向,而且参数传递是指针。所以就觉得答案是7;

然而通过测试发现答案依然是5,那么问题来了,究竟是什么原因呢?

 通过看一些网友的资料明白:通过指针传递参数,其实质仍然是值传递,即是传递指针本身的地址。或者这样说更容易理解一些,即在Try_change中操作的形参,它不会改变实参的值,因此答案依然是5.

或者可以这样形象理解,形参是进入一个参数的时候临时克隆实参的一个家伙,这个家伙继承了实参的所有值,然而他和实参却是两个不同的家伙,Try_change函数内所有发生的行为只和形参有关,当函数结束的时候形参就会灰飞烟灭。而它所做的一切实参是没有丝毫影响的。

 

下面详细用代码分析这个例子,看上面的YY是否成立。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include<stdio.h>
void Try_change( int *p)
{
         int b=7;
         printf ( "Try p=%p &p=%p\n" ,p,&p);
         p=&b;
}
int main()
{
         int *p=NULL;
         int a=5;
         p=&a;
         printf ( "main p=%p &p=%p\n" ,p,&p);
         Try_change(p);
         printf ( "%d\n" ,*p);
         return 0;
}

 输出的结果是:

这里我们可以看到:主函数中的指针和Try_change中的指针虽然值是一样的,但是地址却是不一样的,即他们属于两个不同的指针变量,只是值相等罢了。

到这里似乎真相大白了:指针作为参数在函数中传递的时候,它的实质依然是值传递,形参只是实参的一份拷贝,他们分别属于不同的两个指针变量。

 

 

这样也就顺理成章的解决了很多其他问题:

比如:

在主函数有:int a=5; int *p=&a;  Try(p);

子函数有:int b=7;*p=b;

此时主函数最后输出b的值为7,这是因为虽然子函数中的指针是拷贝的,但是该指针的值也是a的地址,因此在子函数内进行对a的地址产生新的值的时候,主函数内的b也随之改变。

 在例如,使用形参分配内存的例子,也是显而易见的错误:

1
2
3
4
5
6
7
8
9
10
void GetMemory( char * p)
{
    char *p = new char [100];
}
void main()
{
    char *str;
    GetMemory(str);
    strcpy (str, "hi" ); // str = NULL
}        

 因为这里的p和str本质上已经不是一个东东了。

我似乎明白了什么,一直以来为什么这么菜,因为从来没有静下心来思考每一个自己恍惚的问题!

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值