学了四年的计算机,一直让自己比较苦恼的问题是C语言的参数传递问题,之所以说是苦恼,是因为在某年的一个学期,不幸接触到数据结构,光一个链表就把自己弄得死去活来的,而且自已一直就楞以为在操作的过程中,传递参数的指针也在发生变化,结果可想而知,数据结构成了自己专业课里面险些挂彩的一门课程。

直至最近,拿出数据结构打算恶补一下前些年欠下的债,第一件事情,还是先解决好当时困扰自己半年之久的C语言参数传递问题吧。

C语言课堂上,自己明明记得参数传递问题我已经搞懂了,只不过当时没有接触过C plus plus,所以除了值传递和地址传递,我就根本不知道还有一种引用传递。现在想起来,自己那时候学的还是马马虎虎,太过自信认为自己已经完全掌握参数传递的实质。闲话少说,直入正题。

C语言中,函数参数传递有三种形式:值传递、地址传递和引用传递。

弄懂C语言参数传递之前,我们先要清楚以下几个概念:函数参数中的形式参数和实际参数

首先定义上面

形式参数:形参出现在函数定义中,在整个函数体内都可以使用,离开该函数则不能使用。

实际参数:实参出现在主调函数中,进入被调函数后,实参变量也不能使用。

形参和实参的功能是作数据传送。发生函数调用时,主调函数把实参的值传送给被调函数的形参从而实现主调函数向被调函数的数据传送。

函数的形参和实参具有以下特点:

1. 形参变量只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只有在函数内部有效。函数调用结束返回主调函数后则不能再使用该形参变量。

2. 实参可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须具有确定的值,以便把这些值传送给形参。因此应预先用赋值,输入等办法使实参获得确定值。

3. 实参和形参在数量上,类型上,顺序上应严格一致,否则会发生类型不匹配”的错误。

4. 函数调用中发生的数据传送是单向的。即只能把实参的值传送给形参,而不能把形参的值反向地传送给实参。 因此在函数调用过程中,形参的值发生改变,而实参中的值不会变化。

对于函数参数值传递形式,其参数传递的过程是:

(1)行参与实参各占一个独立的存储空间。

(2)行参的存储空间是函数被调用时才分配的。调用开始,系统为行参开辟一个临时存储区,然后将各实参之值传递给行参,这时行参就得到了实参的值。

(3)函数返回时,临时存储区也被撤销。

传值的特点:单向传递,即函数中对行参变量的操作不会影响到调用函数中的实参变量。

示例:

 #include <stdio.h>

以下为值传递的被调函数

 void change_by_value( int x ){
//函数change_by_value接受的参数即为形参 x = x + ; //x的值为13,但其值的变化不会影响到a的值
}

主函数,调用被调函数并输出

 int main(){
int a = ;
printf( " a = %d\n" , a );
change_by_value( a ); // 此时的a作为实参传递给函数
printf( "a = %d\n",a ); //a的值并没有改变
return 0; }

程序的输出为:

a = 3

a = 3

void change_by_value(int x)内部发生的动作应当是当函数被调用时(堆栈调用)在堆栈上临时分配了一块区域,调用结束,出栈。其详细解释如下:

 void change_by_value( int x ){
int _x = x;  //拷贝一份传递给临时变量_x
_x = _x + ;  //改变的是_x,不是x
}

对于函数参数地址传递形式,其原理和值传递方式一样,当调用函数时也要为形式参数分配内存,被调函数执行完毕后也要回收内存。不同的是:地址传递传递的是实参变量地址的拷贝值,而不是实参变量的值。被调函数中对地址所指对象的操作会改变实参的值。例如:

 #include <stdio.h>

以下为地址传递的被调函数

 void change_by_address( int *x ){
*x = *x + ;
}

主函数,用于调用被调函数

 int main(){
int a = ;
printf( "a = %d\n", a );
change_by_address( &a ); //如果定义的不是指针变量或者数组,变量名前要加上取址符号
printf( "a = %d\n", a );
return ;
}

程序输出为:

a = 

a = 

地址传递方式:参数是地址

 void change_by_address( int *x ){
*x = *x + ;
}

实参和行参共享一个存储单元,对行参的操作相应的就改变了实参,此时参数传递是双向的。

小结:

值传递:作为参数的变量,传递给函数执行后,自己的变量值是不变的。它(实参)仅仅只是把值赋给了形参,自己实际上是没有参与函数运算的,参与的是形参,这个就是参数的值传递。值传递好比是你把文件复制一份,通过网络传给他,然后他可以在他本机上对文件做任何的修改,修改会保存下来,但是你机器上的文件不会发生任何的变化。即形参与实参是两个不同的变量,各自占用不同的存储单元。
地址传递:地址传递跟值传递也没有什么不同,值传递是把变量的值传递给形参去参与函数运算,而地址传递则把变量的地址传递给形参去参与函数运算。当然,如果函数改变了变量地址的值,实参的值也会变化的。地址传递好比是你把文件在网络上的地址告诉他人,他人通过网络访问你机器上的文件,他可以对文件进行修改并保存,此时,文件的内容就会发生变化。即形参与实参是相同的变量,占用同一段内存空间。

C语言之参数传递的更多相关文章

  1. C语言的参数传递

    一.三道考题 开讲之前,我先请你做三道题目.(嘿嘿,得先把你的头脑搞昏才行……唉呀,谁扔我鸡蛋?) 考题一,程序代码如下:void Exchg1(int x, int y){   int tmp;  ...

  2. 菜鸟学习-C语言函数参数传递详解-结构体与数组 分类: C/C++ Nginx 2015-07-14 10:24 89人阅读 评论(0) 收藏

    C语言中结构体作为函数参数,有两种方式:传值和传址. 1.传值时结构体参数会被拷贝一份,在函数体内修改结构体参数成员的值实际上是修改调用参数的一个临时拷贝的成员的值,这不会影响到调用参数.在这种情况下 ...

  3. C语言函数参数传递

    1.值传递 void swap(int x,int y) { int temp = x; x = y; y = temp; } void main() { , b = ; swap(a, b); } ...

  4. OpenGL12-shader(GLSL)着色语言2-(参数传递)(代码以上传)

    上一篇中介绍了如何使用shader,用来一个最简单的shader,计算顶点的位置,调用了 OpenGL 顶点着色语言中的内置变量对顶点进行操作,这一例程中,将展示如何将应用层 的数据传递到shader ...

  5. C语言中的参数传递

    有空看看: c语言 函数传输传递的三种方式(值.指针.引用) C语言之参数传递 C语言形参和实参,传值调用和引用调用的区别

  6. R语言参数传递 按引用传递

    R 语言的参数传递是按照引用传递的,二者共享内存 如果想要按值传递 使用函数 copy()

  7. java 参数传递是引用传递还是值传递?

    JAVA的参数传递倒底是值传递还是引用传递,我觉得两种说法都没错,关键是看怎么理解“引用”和“引用传递”. (一)从编译原理的角度讲,所有那些无法通过形参来修改实参本身的传递机制都是“值传递”,在JA ...

  8. Java的参数传递是值传递还是引用传递

    当一个对象被当作参数传递到一个方法后,在此方法内可以改变这个对象的属性,那么这里到底是值传递还是引用传递?  答:是值传递.Java 语言的参数传递只有值传递.当一个对象实例作为一个参数被传递到方法中 ...

  9. Java的参数传递是「按值传递」还是「按引用传递」?

    JAVA传递的只有值,.传递的都是栈里的的值,只是有些栈里面的是值.有的是内存地址.(原文传递的都是栈里的的值有误,局部变量在栈中,成员变量在堆中,类变量(静态变量和常量)在方法区中,可以看做本文的变 ...

随机推荐

  1. IPAdr.exe破解[练手]

    [文章标题]: IPAdr.exe破解[软件名称]: IPAdr.exe[加壳方式]: 无[编写语言]: delphi[使用工具]: OD[作者声明]: 失误之处敬请诸位大侠赐教!---------- ...

  2. github上一款特别的侧滑

    知识分享: 首先看图,我只是大自然的搬运工,想实现这种特效的请点击连接下载github地址忘掉了,....http://download.csdn.net/detail/lj419855402/860 ...

  3. File的保存与读取

    import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io ...

  4. 从0开始学Java——JSP&Servlet——如何部署web应用程序

    web容器要求应用程序部署时,需要像下面这样组织其目录结构: 手动去创建这样的目录结构还是挺麻烦的,所幸我们有开发工具,所以可以像下面这样来部署一个web项目. 1)确认程序代码已经完成: 2)在ec ...

  5. 动态下载苹果系统提供的多种中文字体(适合对字体有较多需求的应用比如阅读类的app)

    链接:https://developer.apple.com/library/ios/samplecode/DownloadFont/Listings/DownloadFont_ViewControl ...

  6. 20145302张薇 GDB调试汇编堆栈过程分析

    GDB堆栈跟踪与汇编调试 堆栈跟踪 源代码 使用gcc - g example.c -o example -m32指令在64位的机器上产生32位汇编,然后使用gdb example指令进入gdb调试器 ...

  7. 浅析Java异常

    1.什么是异常 结构不佳的代码不能运行,这是Java的基本理念. 发现错误的理想时机是在编译期.然而,编译器并不能发现所有的错误,余下的问题就需要在程序运行时解决.这就需要错误能通过某种方式,把适当的 ...

  8. CSS 居中大全(转)

    转自这里,收藏备用. <center> 不建议用了. text-align:center 在父容器里水平居中 inline 文字,或 inline 元素 vertical-align:mi ...

  9. Javascript基础系列之(八)Javascript的调试与优化

    Javascript的错误主要是语法错误和运行时的错误,前者在代码解析时就会出错,影响程序的运行.后者称为异常,影响它所运行的线程.下面就Javascript常见错误进行分析 1.常见的错误和异常 i ...

  10. HTML5——地图应用

    我们就拿百度地图举例吧: 废话少说,直接上Demo 简要截图如下:' 简要代码如下: <!DOCTYPE html> <html> <head> <title ...