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

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

#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是否成立。

#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也随之改变。

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

            void GetMemory(char* p)
            {
               char *p = new char[100];
            }
            void main()
            {
               char *str;
               GetMemory(str);
               strcpy(str, "hi"); // str = NULL
            }

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

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

时间: 2024-10-26 17:16:00

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

C++ 二维数组(双重指针作为函数参数)

本文的学习内容参考:http://blog.csdn.net/yunyun1886358/article/details/5659851 http://blog.csdn.net/xudongdong99/article/details/6723163 1.使用二维数组作为形参的例子: void func(int arr[][10]) { } int main() { int array[10][10]; func(array); //用二维数组名作为实参,调用函数 } 上面的例子可以编译通过,

通过操作指针,与指针做函数参数&#39;实现字串在主串中出现的次数,然后将出现的部分按照要求进行替换

#include<stdio.h> #include<stdlib.h> int strTime(const char *str1, const char *str2, int *time) { int count = 0; char *p1 = str1; char *p2 = str2; //p1是第一次出现的位置 p1 = strstr(p1, p2); //注意这里不要写成*p1!=NULL 因为p1 是null的地址一旦读取*p1 会出错的!!!!不能读取操作系统的数据

Day8 函数指针做函数参数

课堂笔记 课程回顾 多态 virtual关键字 纯虚函数 virtual func() = 0; 提前布局vptr指针 面向接口编程 延迟绑定 多态的析构函数的虚函数. 多继承的二义性 . 重载 重写 重定义. 实现多态的理论基础:函数指针做函数参数. vptr指针与虚函数表. 构造函数不应为虚函数 多态会降低程序的执行速度.不建议所有的函数都是虚函数. 多态时的指针步进. 多继承在项目开发中使用的比较少. linux从2.4内核升级到2.6的时候,做到了电源可以热插拔,提前将电源驱动的接口规划

指针作为函数参数,修改实参值

1,指针作为函数参数, 指针可以指向内存中任意一个数据,通过间接引用能够在函数内修改函数外甚至系统中的数据; 为了避免指针作为函数参数导致数据被意外修改,我们可以使用const来保护指针所指向的数据; 2,指针作为函数返回值, 同别的数据类型int,float一样,指针也能够作为函数的一种返回值类型,把返回指针的函数称为指针函数; 返回的指针所指向的数据不能够是函数内部声明的变量; 更灵活的存储,使用数组的时候面临种尴尬:数组的存储空间必须在程序运行前申请,即数组的大小在编译前必须是已知的常量表

二级指针作为函数参数的典型用法

用二级指针作为函数参数,有两种典型情况:1.需要传递一级指针的数组时:例如标准C的main函数:int main(int argc, char*[] argv),数组最高维可以退化,char*[] argv等价于char** argv.这里argv代表命令行参数数组.2.需要对传入的一级指针进行修改时:例如:void alloc_new_char_array(int n, char** t){*t = (char*)malloc(n * sizeof(t));}这里可以通过返回值达到相同的效果,

用指针做函数参数的好处,

用指针做函数参数的好处, 首先要理解函数传参的过程,函数传参是复制型的,例如 void modify(int a) { a++; } void main() { int a=5; modify(a); printf("%d",a); } 程序执行完之后,a的值还是5,为什么呢,因为在执行modify函数的时候,是另外开辟了存储空间,将a的值复制过去,然后modify函数所进行的所有操作都是针对这个新开辟的空间而言的,因此程序执行完之后,a的值并没有发生改变, 如果我们用指针去传递参数,

指向结构体变量的指针作函数参数

 /********************* * 指向结构体变量的指针作函数参数 * ***********************/ #include<stdio.h> #include<string.h> struct student {  int num;  char name[20];  //char *name;    //若定义为指针则应与下面 stu.name = "jacob"; 配对使用,交叉使用则会报错                 //

C++基础8【难】 回顾:数组指针,函数指针,函数指针做函数参数 C语言多态

1,数组指针语法梳理 回顾,如何定义数组数据类型: 回顾,如何定义指针类型数组: 回顾,如何直接定义 一个指向数组类型的指针: 2,函数指针语法梳理 1)如何定义一个函数类型 2)如何定义一个函数指针类型 3)如何定义一个函数指针(指向一个函数的入口地址) [中级程序员 转 高级程序员的 必经之路] 1,函数类型做函数的参数 把函数的入口地址传过来,奇怪的效果:[多态就是这样] 函数指针 做 函数参数 思想剖析 1,数组指针语法梳理 回顾,如何定义数组数据类型: [email protected

C和C++函数指针作为函数参数的区别

1.函数作为参数加*和不加* 例1: void print(int i) { printf("not parameter%d\n",i); } void debugfun(void <span style="color:#ff0000;">(*funprint</span>)(int)) { funprint(2); return; } main() { debugfun(print); } 输出: not parameter2 例2:(去掉