C函数的“传值调用”和“传址调用”的深入分析

目录

传值调用

传址调用

指针参数的妙用


     C中函数一般都有形参,当然也有形参为void的函数,对于那些有形参的函数,我们在调用的时候,就涉及到参数的传递,我们常见的参数有2种,一种是标准变量参数,比如int、char、结构体等单独变量,另一种就是指针,指针可以是一级指针,也可以是多级指针。

传值调用

   对于上面说的第1种,函数的参数是标量参数,我们在调用函数,给函数传递参数时,是按照“传值调用”来运行函数的,这意味着函数将获得函数值的一份“拷贝”,注意这里说的是拷贝,这意味着我们可以放心的修改这个拷贝值,而不必担心会修改调用程序实际传递给他的参数,这其实还意味着,我们完全可以不用再额外定义一个中间变量去计算数值,先看个代码案例:

int func1(int a)
{
    int b;
    b = a + 1;
    return b;
}

int func2(int a)
{
    a = a + 1;      //没错,我们可以直接这么用,而不用
    return a;
}

int main(void)
{
    int a0 = 5;
    func1(a0);
    func2(a0);
}

  这两个函数的结果是一模一样的,不过func1在函数内部又定义了一个中间变量b,这么做看起来好像更保险一些,但是其实完全没有必要,反而是func2更加简洁。如果我们对这个理解起来有些模糊,首先可以参考之前的文章《CPU执行程序的简单理解》,我们进一步的解释一下,我们知道C函数的运行,CPU或者说是操作系统,会给该函数自动分配一段内存,这段内存是从“栈”中申请的(栈是个好东西,是程序运行的大功臣),上面的两个函数我们可以简单的画一下他们的运行内存结构:

     我们可以简单的认为,在函数运行时,会给函数的参数自动分配对应的内存,我们在调用函数时,给函数传递的是“值的拷贝”,也就是我们会在对应的内存里写入 那个拷贝的值,既然是拷贝,所以完全不用担心会修改调用程序实际传递给她的参数,也就是上面实例代码中 变量 a0 的值并不会被修改。

传址调用

    前面的文章,我们详细分析过指针的概念,本质上,指针也是一个“值”,跟标准变量是一样的,只不过这个“值”规定好了,一定是一个“地址”,我们只能对地址进行简单的加减操作,多数情况下,我们通过对该地址值进行 引用操作,获取这个地址里的内容,所以,我们调用参数为指针的函数时,传递给函数的也是这个指针地址的拷贝,也就是所谓的“传递地址调用”,我们还是来举例分析:

void func(int *a)
{
   *a = *a + 1;   
}

int main(void)
{
    int a = 5;
    func(&a);
}

  从上面的代码可知,我们在调用函数func时,传递的是变量a的地址,而在func函数内部,“*”操作符的含义是间接引用,就是给a表示的地址中的内容进行操作,由于C语言中规定,“=” 右侧的优先级要高于左侧的优先级,所以 *a = *a + 1的计算可以理解成分两部,先计算 *a + 1,也就是对a所指向的地址取其内容并 加1,然后将计算结果再赋值给 a 指向的内存区域。经过上述函数的调用后,a的值就变成了6,  我们再来简单的绘制下函数运行时的内存分布。

  这里特别强调下,尽管在调用函数时,我们传入的是一个地址的值的拷贝,但是对“地址”的操作,就不是函数局部操作了,而是针对整个内存区域了,所以对该地址的间接操作(*)就是对这个地址指向的内存区域进行读写,所以这次的调用会改变a的值。

指针参数的妙用

    对于标量参数,其实比较简单,相当于一个计算器,输入值,得到结果,而指针参数的框架,虽然我们传入的是一个“地址”值,但是只要有这一个地址值,理论上我们可以对这个地址值 上下 n个地址的内存进行操作,这就意味着:

(1)我们可以通过指针参数,传递多个数据,而不是通过多个标参。这里说的 多个数据可以是很多。比如在操作系统编程中,我们创建新的线程时,如果想要给新线程传递参数,就是通过一个(void *)指针来进行参数传递的。当然了,我们传递的指针,必须是有效地址,“有效”的含义是,要么是通过数组定义、静态变量,要么是通过动态内存申请(malloc),不能随便传递一个野指针,毕竟我们在函数或者线程中,对该指针进行间接操作时,尤其进行“写”操作,会非常危险。

(2)比较简单的,我们通过指针参数,可以实现一个函数返回n个数据,当然这个前提也是我们要提前分配好存放着n个数据的内存区域,比如数组或动态内存分配。

发布了247 篇原创文章 · 获赞 257 · 访问量 62万+

猜你喜欢

转载自blog.csdn.net/u012351051/article/details/92846262