[C]值传递、指针传递、引用传递

C语言值传递怎么用,引用传递怎么用?

以表格来简要说明并区分这几种传递到底在做什么:

类型传递对象传递行为内存关系适用情况区别与联系举例
值传递数值将实参的数值拷贝到另一块独立的内存上,在新的内存上操作形参和实参占用不同的内存函数内部需要修改参数,并且希望此改变的作用域不涉及调用者传递是单向的,实参->形参函数调用时,参数为数值
地值传递地址直接在实参所在的内存上操作形参指向的和实参所在的是一块内存内部对变量进行操作,并且希望此操作的作用域包括调用者;返回值传递传递是双向的,实参<->实参函数调用时,参数为地址
引用传递别名同上形参和实参是同一个变量的不同名字,拥有相同的内存同上同上实参代替了形参

具体说来,引用/地址传递在返回值传递上的应用是指:
假设函数需要有多个返回值,而显式上不能有返回值或者只能有一个返回值,则此时可利用指针/引用传递,对其他需要返回的变量进行修改,并将修改返回给调用者,完成隐式的返回值传递。
下面我们用代码来直接证明这三种传递在做什么:

#include<iostream>
#include<stdlib.h>
using namespace std;

void swap_value(int a, int b){
    cout << "swap 前,形参的数值和地址:" << endl;
    cout << "value(a) = " << a << "," << "变量a的地址:" << &a << endl;
    cout << "value(b) = " << b << "," << "变量b的地址:" << &b << endl;
    int tmp;
    tmp = a;
    a = b;
    b = tmp;
    cout << "swap 后,形参的数值和地址:" << endl;
    cout << "value(a) = " << a << "," << "变量a的地址:" << &a << endl;
    cout << "value(b) = " << b << "," << "变量b的地址:" << &b << endl;

}

void swap_adress_value(int *a, int *b){
    cout << "swap 前,形参的地址和指向的数值:" << endl;
    cout << "value(a) = " << a << "," << "*a:" << *a << endl;
    cout << "value(b) = " << b << "," << "*b:" << *b << endl;
    int *tmp;
    tmp = a;
    a = b;
    b = tmp;
    cout << "swap 后,形参的地址和指向的数值:" << endl;
    cout << "value(a) = " << a << "," << "*a:" << *a << endl;
    cout << "value(b) = " << b << "," << "*b:" << *b << endl;

}

void swap_pointer(int *a, int *b){
    cout << "swap 前,形参的地址和指向的数值:" << endl;
    cout << "value(a) = " << a << "," << "*a:" << *a << endl;
    cout << "value(b) = " << b << "," << "*b:" << *b << endl;
    int tmp;
    tmp = *a;
    *a = *b;
    *b = tmp;
    cout << "swap 后,形参的地址和指向的数值:" << endl;
    cout << "value(a) = " << a << "," << "*a:" << *a << endl;
    cout << "value(b) = " << b << "," << "*b:" << *b << endl;

}

void swap_reference(int &a, int &b){
    cout << "swap 前,形参的地址和指向的数值:" << endl;
    cout << "value(a) = " << a << "," << "a存储地址:" << &a << endl;
    cout << "value(b) = " << b << "," << "b存储地址:" << &b << endl;
    int tmp;
    tmp = a;
    a = b;
    b = tmp;
    cout << "swap 后,形参的地址和指向的数值:" << endl;
    cout << "value(a) = " << a << "," << "a存储地址:" << &a << endl;
    cout << "value(b) = " << b << "," << "b存储地址:" << &b << endl;

}

int main(){
    cout << "值传递:" << endl;
    int x = 10;
    int y = -1;
    cout << "swap 前,实参的数值和地址:" << endl;
    cout << "value(x) = " << x << "," << "变量x的地址:" << &x << endl;
    cout << "value(y) = " << y << "," << "变量y的地址:" << &y << endl;
    swap_value(x, y);

    cout << "swap 后,实参的数值和地址:" << endl;
    cout << "value(x) = " << x << "," << "变量x的地址:" << &x << endl;
    cout << "value(y) = " << y << "," << "变量y的地址:" << &y << endl;


    system("pause");
    cout << endl;
    cout << endl;
    cout << endl;

    cout << "传递地址且对地址进行修改:" << endl;
    x = 10;
    y = -1;
    cout << "swap 前,实参的数值和地址:" << endl;
    cout << "value(x) = " << x << "," << "变量x的地址:" << &x << endl;
    cout << "value(y) = " << y << "," << "变量y的地址:" << &y << endl;
    swap_adress_value(&x, &y);

    cout << "swap 后,实参的数值和地址:" << endl;
    cout << "value(x) = " << x << "," << "变量x的地址:" << &x << endl;
    cout << "value(y) = " << y << "," << "变量y的地址:" << &y << endl;

    system("pause");
    cout << endl;
    cout << endl;
    cout << endl;

    cout << "指针传递:" << endl;
    x = 10;
    y = -1;
    cout << "swap 前,实参的数值和地址:" << endl;
    cout << "value(x) = " << x << "," << "变量x的地址:" << &x << endl;
    cout << "value(y) = " << y << "," << "变量y的地址:" << &y << endl;
    swap_pointer(&x, &y);

    cout << "swap 后,实参的数值和地址:" << endl;
    cout << "value(x) = " << x << "," << "变量x的地址:" << &x << endl;
    cout << "value(y) = " << y << "," << "变量y的地址:" << &y << endl;

    system("pause");
    cout << endl;
    cout << endl;
    cout << endl;

    cout << "引用传递:" << endl;
    x = 10;
    y = -1;
    cout << "swap 前,实参的数值和地址:" << endl;
    cout << "value(x) = " << x << "," << "变量x的地址:" << &x << endl;
    cout << "value(y) = " << y << "," << "变量y的地址:" << &y << endl;
    swap_reference(x, y);

    cout << "swap 后,实参的数值和地址:" << endl;
    cout << "value(x) = " << x << "," << "变量x的地址:" << &x << endl;
    cout << "value(y) = " << y << "," << "变量y的地址:" << &y << endl;

    system("pause");
    cout << endl;
    cout << endl;
    cout << endl;

}

再来看执行结果:

值传递:
swap 前,实参的数值和地址:
value(x) = 10,变量x的地址:0046FD4C
value(y) = -1,变量y的地址:0046FD40
swap 前,形参的数值和地址:
valuea) = 10,变量a的地址:0046FC68
value(b) = -1,变量b的地址:0046FC6C
swap 后,形参的数值和地址:
valuea) = -1,变量a的地址:0046FC68
value(b) = 10,变量b的地址:0046FC6C
swap 后,实参的数值和地址:
value(x) = 10,变量x的地址:0046FD4C
value(y) = -1,变量y的地址:0046FD40
请按任意键继续. . . 



传递地址且对地址进行修改:
swap 前,实参的数值和地址:
value(x) = 10,变量x的地址:0046FD4C
value(y) = -1,变量y的地址:0046FD40
swap 前,形参的地址和指向的数值:
valuea) = 0046FD4C,*a:10
value(b) = 0046FD40,*b:-1
swap 后,形参的地址和指向的数值:
valuea) = 0046FD40,*a:-1
value(b) = 0046FD4C,*b:10
swap 后,实参的数值和地址:
value(x) = 10,变量x的地址:0046FD4C
value(y) = -1,变量y的地址:0046FD40
请按任意键继续. . . 



指针传递:
swap 前,实参的数值和地址:
value(x) = 10,变量x的地址:0046FD4C
value(y) = -1,变量y的地址:0046FD40
swap 前,形参的地址和指向的数值:
valuea) = 0046FD4C,*a:10
value(b) = 0046FD40,*b:-1
swap 后,形参的地址和指向的数值:
valuea) = 0046FD4C,*a:-1
value(b) = 0046FD40,*b:10
swap 后,实参的数值和地址:
value(x) = -1,变量x的地址:0046FD4C
value(y) = 10,变量y的地址:0046FD40
请按任意键继续. . . 



引用传递:
swap 前,实参的数值和地址:
value(x) = 10,变量x的地址:0046FD4C
value(y) = -1,变量y的地址:0046FD40
swap 前,形参的地址和指向的数值:
valuea) = 10,a存储地址:0046FD4C
value(b) = -1,b存储地址:0046FD40
swap 后,形参的地址和指向的数值:
valuea) = -1,a存储地址:0046FD4C
value(b) = 10,b存储地址:0046FD40
swap 后,实参的数值和地址:
value(x) = -1,变量x的地址:0046FD4C
value(y) = 10,变量y的地址:0046FD40
请按任意键继续. . . 



      我们结合运行结果来分析一下:
      调用swap_xxx函数之前,变量x,y分别有自己的地址和数值。
      调用函数swap_value时,相当于做了以下2个赋值操作:

a = x;b = y;

     这只是说把x、y的value分别赋给a、b。
     可以通过结果看出,a、b有自己的内存,内存地址与x、y不同。且调出swap_value之后,发生数值交换的仅是内部变量而已,外部变量x、y的地址和数值并没受到影响。
     调用swap_adress_value/swap_pointer时,相当于做了以下2个赋值操作:

*a = &x*b = &y

     这里&是取地址的意思,是把x、y的地址分别赋给指针变量a、b,也就是说a有自己的内存地址,这块内存存储的就是x的地址,也即a指向了x。
     只不过,在函数swap_adress_value内部,只是将指针变量a和b的value做了交换。所以外部变量x、y不受任何影响,而内部变量a、b有自己的内存地址,a和b的地址未发生改变,但是a和b的value改变了,a和b指向的变量改变了。
     而在swap_pointer里面,则是将a和b指向的内容作了交换,a和b的value未发生改变,依然指向之前的内存,但是它们指向的内存里面所存储的内容作了交换。同时在外部,x和y依然对应着原来的内存,所以x和y的地址都没有改变,但是里面写入的值却发生了改变。也就是说内部变量交换的时候,是在外部变量所对应的同一块内存空间上进行的。
     调用swap_reference时,相当于做了以下2个赋值操作:

&a = x;&b = y;

     这里&是引用的意思,是说a和x对应着同一块内存,对其中任何一个的修改,另一个都会受到影响,a和x相当于同一个变量的两个名字。所以内部变量a和x的地址一样,数值一样。交换之后,a和x的数值、地址依然一样。

#define
#ifdef的用途
#include的作用

#include是文件包含指令,在程序编译时,把#include后面指定文件的内容包含进当前的文件中。主要有2种形式:
1、#include<file.h>
从标准库中寻找file.h文件,是系统库头文件,根据一定的规则查找filh.h。
2、#include”file.h”
从工程目录下开始寻找file.h文件,是自定义的头文件,在源文件所在位置查找filh.h。

typedef
C语言工程的编译过程

如下图所示:
这里写图片描述

C程序的内存分布
数组的初始化
数组和指针的联系与区别
为什么数组不能更改指向地址?这样设计的动机是什么?
void指针是什么?
函数指针怎么定义?
函数指针的用途是什么?
malloc和free,什么时候需要用它们?
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值