C语言函数的参数传递实例:利用函数交换两个变量的值

标签: 函数 c语言
26人阅读 评论(0) 收藏 举报
分类:

交换两个变量的值,容易联想到【两量交换借助中间变量】的方法。

若用函数调用的方式来实现交换,沿用上述思路初步实现如下:

#include<stdio.h>
void exchange(int,int);
void exchange(int one,int another){
    int t;
    t = one;
    one = another;
    another = t;
}
int main(){
    int num1;
    int num2;
    printf("输入需要交换的两个数:\n");
    scanf("%d %d",&num1,&num2);
    exchange(num1,num2);
    printf("交换后的两个数为:%d %d\n",num1,num2);
    return 0;
}

结果说明,未能完成交换。

回看上述程序实现的方式,涉及到了函数传递中至关重要的问题—实参和形参之间的关系。

【notes】

1.形参: formal argument,形式参数

它是被调函数中的局部变量,每当调用函数时,这些变量就会被赋值。它只在被调用时才会被分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只在函数内部有效。

2.实参: actual argument

它是调用函数分配给被调函数变量的特定数值,可以是常量/变量或一个表达式。执行时,首先要计算其值,然后将该值复制一份给被调函数中相应的形参。

既然被调函数使用的值是从调用函数中复制而来的,所以不管在被调函数中对复制的数值进行什么操作,调用函数中的原数值不会受到任何影响。

这好比原件和复印件之间的关系:在复印件上做的任何改动都不会对原文件造成丝毫影响。

因此,上述程序中,num1和num2虽然成功把值传给了one、another,one、another也完成了它们之间数值的交换,但是也仅仅是one、another之间交换了,和num1和num2本身没有关系。

这是一次单向的值传递过程,函数exchange的实参能传给形参,但**形参**one、another是定义在函数exchange中的局部变量,当函数调用结束后,它俩就会被释放,因此它们没有渠道把交换的值传回给需要交换的num1,num2。

既然想要通过函数调用的方式来解决这个问题,先来了解函数调用的具体实现过程。

首先,各个函数都有一定的堆栈空间。函数形参和实参的传递需要依赖系统堆栈来实现

【堆栈基础知识】

  • 栈:由操作系统自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。

  • 堆(操作系统): 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收

  • 在堆栈中变量分布是从高地址到低地址分布

现在继续来看函数调用的过程.

step1:

>--主函数调用子函数,实参入栈。(若实参为表达式,则从右向左依次的将实参表达式的值计算出来)

按本文一开始提到的例子来说,即就是num1和num2入栈,而实参num1,num2在系统堆栈中所占用的空间,就是与之对应的形参变量的空间。

这意味着已经完成了”参数传递”:

num1的地址赋值给了one所指向的空间—> * one = &num1;

num2的地址赋值给了another所指向的空间—> * another= &num2;

step2:

>-- 通过call汇编指令,调用子函数,将eip入栈,再通过ret指令出栈,并赋值给eip,从而保证函数调用及返回顺序的正常。

由于函数调用的时候是汇编中的地址的跳转,而在汇编中的跳转源于标号地址IP。

所以这里就要涉及到汇编相关的知识

【note】

  • eip:寄存器存放下一个CPU指令存放的内存地址,当CPU执行完当前的指令后,从EIP寄存器中读取下一条指令的内存地址,然后继续执行。

  • esp:寄存器存放当前线程的栈顶指针

  • ebp:寄存器存放当前线程的栈底指针

ESP指向栈顶,程序执行时移动,ESP减小分配空间,ESP增大释放空间,ESP又称为栈指针。

汇编相关的具体细节待日后充实完善。

call指令的执行过程大致如下:

1) call指令首先将主调函数在子函数返回后要执行的下一条指令的地址入栈(返回地址此时在栈顶),然后,更改eip的值,以开始执行子函数的第一条指令,从而开启子函数的执行。

2) 当子函数运行结束后,执行ret指令,这将导致处在栈顶的返回地址出栈,并更改eip的值,返回主调函数下一条指令。

step3:

>--编译器将栈底指针移动到栈顶位置,再将堆栈当前栈底向上的空间分配给子函数的局部变量

step4:

>-- 子函数运行结束后,恢复到以前的栈底和栈顶指针。栈顶指针再减去形参变量所占用的空间,恢复到子函数调用之前的状态。

现在再来解决最初的问题:利用函数调用来实现两个变量的交换:

#include<stdio.h>
void Exchange(int *one, int *another);
void Exchange(int *one, int *another){
    int temp;
    temp = *one;
    *one = *another;
    *another = temp;
}
void main(void){
    int num1;
    int num2;
    printf("输入两个需要交换的数\n",num1,num2);
    scanf("%d %d",&num1,&num2);
    Exchange(&num1,&num2);//实参类型为首地址
    printf("交换完毕后两个数的值为%d%d\n",num1,num2);
}


运行结果:

查看评论

如何通过调用函数交换两个变量的值及常见误区

大家都知道c语言中交换两个变量的值,需要以下代码:
  • csdnAaron
  • csdnAaron
  • 2014-10-24 19:30:20
  • 3678

C语言利用指针在函数中交换两个数的思考

这个是一个深刻理解指针和函数的问题。本来自己当初很认真的看过这个问题,可是现在搞运维去了,对linux倒是挺熟的,结果把以前的知识忘了。哎,真是悲哀。今天突然有个s b问我,我一时还有点懵,这里记录一...
  • qq_25417713
  • qq_25417713
  • 2016-12-15 22:18:57
  • 7426

C语言小程序--交换两个变量的值

看到这个题目首先我们可以想到借助一个第三变量来实现 例如:a=10,b=20  我们想要交换a与b的值,可以借助一个第三变量temp,把a的值附给temp,把b的值给a,再把temp的值给b,就完成了...
  • her__0_0
  • her__0_0
  • 2016-03-16 20:58:35
  • 7469

编写一个函数,用于交换两个变量的值

C语言(地址传递): void Swap(int *a,int *b) { int temp; int temp=*a; int *a=*b; int *b=temp; }j...
  • lluozh2015
  • lluozh2015
  • 2015-10-13 12:58:33
  • 2020

C语言交换两个变量数值的几种方法

因为经常见到这类题目,就自己总结了以下几种办法 1. 创建中间变量 这是最快也是最简单的办法,例如:#includeint main() { int a=10; int b...
  • ljx_5489464
  • ljx_5489464
  • 2015-11-25 21:11:29
  • 18150

实现结构体变量交换值的函数

#include #include struct stuff{  char full_name[20];  unsigned age;  unsigned gender;};void swap_str...
  • dzmiao
  • dzmiao
  • 2004-12-27 22:01:00
  • 1123

C语言之交换两个整型变量的值(四种方法)

C语言中有一道题目是交换两个整型变量的值,这是一道非常简单的题目,那么一共有几种方法呢?以下是我整理的四种方法,是在MAC系统x-code环境下编译并运行成功的,以下为截图: 方法一:通过引入第三方...
  • yanda607
  • yanda607
  • 2015-04-23 01:39:35
  • 2700

C语言中交换两个整数的值之传值调用和传址调用

在C语言中,一说到交换两个整数的值,大家第一反应可能是这样的代码。定义一个第三方变量来辅助交换。 #include int main() { int num1 = 10; int num2 = ...
  • JenaeLi
  • JenaeLi
  • 2016-10-02 21:31:13
  • 2202

用C语言实现两变量内容交换的N种方法

一:创建变量实现交换 1.#include int main() { int a = 10; int b = 20; int c; printf("before change:...
  • Erica_ou
  • Erica_ou
  • 2016-09-20 08:21:17
  • 2890

C语言基础—实现两个变量交换的三种方法

C语言程序执行中,当定义了变量后,就相当于在内存中开辟了一部分的存储空间,不同空间存储的内容各异。在实际应用中,常常需要交换不同存储空间的内容,即变量内容的交换。用不同的思路,都能实现两个变量的交换。...
  • zhudong10
  • zhudong10
  • 2015-10-16 21:04:50
  • 1945
    个人资料
    等级:
    访问量: 672
    积分: 30
    排名: 209万+
    文章分类
    文章存档