参数传递

C语言参数传递一般分为:值传递和地址传递(本质上只有值传递

(注意:C语言中没有引用传递,C++才有引用传递,因为很多C语言环境是用C++编译器编译,使得C看起来支持引用传递,导致很多网上很多blog都把引用传递归为C语言参数传递的一类,

当使用Microsoft Visual C++ 2010 Express或VC6之类的编译器时使用引用传递就无法编译通过)

值传递:

形参是实参的拷贝,改变形参的值并不会影响外部实参的值。从被调用函数的角度来说,值传递是单向的(实参->形参)

 #include <stdio.h>

 void swap(int x, int y);

 main()
{
int a = , b = ; swap(a, b);
printf("a=%d\nb=%d\n", a, b); return ;
}
void swap(int x, int y)
{
int t; t = x;
x = y;
y = t;
}

上述代码运行后a、b的值并未改变

地址传递:

形参为指向实参地址的指针,当对形参的指向操作时,就相当于对实参本身进行的操作

 #include <stdio.h>

 void swap(int *x, int *y);

 main()
{
int a = , b = ; swap(&a, &b);
printf("a=%d\nb=%d\n", a, b); return ;
}
void swap(int *x, int *y)
{
int t; t = *x;
*x = *y;
*y = t;
}

上述代码执行后a和b值交换,a=20、b=10

易错点补充:

 #include <stdio.h>

 void swap(int *x, int *y);

 main()
{
int a = , b = ;
int *pp = &a;
int *kk = &b;
swap(pp, kk);
printf("a=%d\nb=%d\n", *pp, *kk); return ;
}
void swap(int *x, int *y)
{
int *t; t = x;
x = y;
y = t;
}

请读者想一下,上述代码执行后a和b的值是否交换,为什么?

上述代码看起来像交换了指针pp和kk的指向,实际上并没有

代码的运行结果a=10、b=20,运行结果是a和b的值并没有改变,因为这时使用的实参pp,kk是值传递,传递的是指针的值,以指针pp来说,指针的值是变量a的地址,

指针的值传入后用形参int *x和int *y接收,这里x和pp虽然都指向变量a的地址,但指针x和pp自身的地址并不相同(意思是x拷贝了一份pp的值),意味着你能改变变量a的值,但是不能改变pp的值(这里与值传递相似)

为了更加直观,清晰的看出值的交换,这里添加一些代码来显示内存和变量的值

 #include <stdio.h>

 void swap(int *x, int *y);

 main()
{
int a = , b = ;
int *pp = &a;
int *kk = &b; printf("a的地址%p----b的地址%p\n\n", &a, &b);
printf("pp的值%p----kk的值%p\n", pp, kk);
printf("pp的地址%p----kk的地址%p\n\n", &pp, &kk);
swap(pp, kk);
printf("a = %d\nb = %d", *pp, *kk); return ;
}
void swap(int *x, int *y)
{
int *t; printf("x的值%p----y的值%p\n", x, y);
printf("x的地址%p----y的地址%p\n", &x, &y); t = x;
x = y;
y = t;
}

从pp和x的地址可以看出,x和pp是两块不同的内存区域,x在swap函数内执行完后并不会对pp值产生任何影响,相当于复制了一份pp的值,如下图

(灵魂画手已上线)

传入指针的值虽然不能对指针的值进行修改,但是可以通过地址直接对a的值进行修改也可以实现交换,代码如下

 #include <stdio.h>

 void swap(int *x, int *y);

 main()
{
int a = , b = ;
int *pp = &a;
int *kk = &b; swap(pp, kk);
printf("a = %d\nb = %d", *pp, *kk); return ;
}
void swap(int *x, int *y)
{
int t; t = *x;
*x = *y;
*y = t;
}

传入指针的值和和传入变量的地址在数值上是一样的,但是一个是传值传递一个地址传递,如下图

(灵魂画手已经上线)

二级指针

上面提到的参数传递方式有,传入变量的值,传入变量的地址,传入指针的值三种参数传递方式

下面介绍第四种,传入指针的地址,上面第二种(传入变量的地址)和第三种(传入指针的值)传递方式使用的用来接收参数的形参都是int *类型的指针

这里因为传入的是指针的地址,所以要使用二级指针int **x,因为传入的指针的地址,实现值的交换的方式就有两种一种是直接对变量的值进行修改,另一种就是对指针的值进行修改

第一种:直接对变量值进行修改

 #include <stdio.h>

 void swap(int **x, int **y);

 main()
{
int a = , b = ;
int *pp = &a;
int *kk = &b; swap(&pp, &kk);
printf("a = %d\nb = %d", *pp, *kk); return ;
}
void swap(int **x, int **y)
{
int t; t = **x;
**x = **y;
**y = t;
}

第二种:对指针的值进行修改

 #include <stdio.h>

 void swap(int **x, int **y);

 main()
{
int a = , b = ;
int *pp = &a;
int *kk = &b; swap(&pp, &kk);
printf("a = %d\nb = %d", *pp, *kk); return ;
}
void swap(int **x, int **y)
{
int *t; t = *x;
*x = *y;
*y = t;
}

注意swap函数里用int *来交换指针的值,而不能用int **来进行交换,读者可自行修改代码验证想一下为什么?

下面是二级指针示意图

(灵魂画手已上线)

若有疑问,欢迎留言

C语言参数传递(值传递、地址传递)+二级指针的更多相关文章

  1. C语言提高 (3) 第三天 二级指针的三种模型 栈上指针数组、栈上二维数组、堆上开辟空间

    1 作业讲解 指针间接操作的三个必要条件 两个变量 其中一个是指针 建立关联:用一个指针指向另一个地址 * 简述sizeof和strlen的区别 strlen求字符串长度,字符数组到’\0’就结束 s ...

  2. C语言复习---二维数组和二级指针的关系:没关系,别瞎想(重点)

    前提:一维数组和一维指针为什么可以替换使用? ] = { , , }; int *p = a; ; i < ; i++) printf("%d ", *(p + i)); 上 ...

  3. C语言 值传递和地址传递

    不少同学在学到C语言的指针部分时感到很困惑,对经常提到的"值传递"和"地址传递"两个概念弄不 明白.实际上,因为地址本身也可以作为一个特殊的"值&qu ...

  4. (C++)函数参数传递中的一级指针和二级指针

    主要内容: 1.一级指针和二级指针 2.函数指针传递的例子 3.什么时候需要传递二级指针? 4.二级指针在链表中的使用 1.一级指针和二级指针 一级指针:即我们一般说的指针,就是内存地址: 二级指针: ...

  5. C语言指针系列 - 一级指针.一维数组,二级指针,二维数组,指针数组,数组指针,函数指针,指针函数

    1. 数组名 C语言中的数组名是一个特殊的存在, 从本质上来讲, 数组名是一个地址, 我们可以打印一个指针的值,和打印一个数组的值来观察出这个本质: int nArray[10] ={ 0 }; in ...

  6. C 真正理解二级指针

    本文转载自CSDN博主liaoxinmeng,做数据结构时遇到指针方面的问题,想了许久,因此我觉得很有必要复习一下二级指针及其使用 正文如下: 指针是C语言的灵魂,我想对于一级指针大家应该都很熟悉,也 ...

  7. C++ 二级指针与 const 关键字

    可用七种不同的方式将 const 关键字用于二级指针,如下所示: //方式一:所指一级指针指向的数据为常量,以下几种为等效表示 const int ** pptc; //方式一 int const * ...

  8. C语言:值传递,地址传递和引用传递(example:值交换)

    于C语言中值传递.地址传递和引用传递的我个人理解. 通过一个例子:swap(交换两个整型变量的值)来表现! #include <stdio.h> void swap1(int* a,int ...

  9. go语言基础之结构体做函数参数 值传递和地址传递

    1.结构体做函数参数值传递 示例: package main //必须有个main包 import "fmt" //定义一个结构体类型 type Student struct { ...

随机推荐

  1. JS 读取本地Excel文件

    首先我们先引用一个Excel的类库xlsx.full.min.js 中间处理: 'use strict'; var ExcelReader = { isFirstRead: true, fixdata ...

  2. 五个步骤搞定敏捷UX设计

    互联网产品发展的速度越来越快,人们对于产品的要求也在不断的升级,这直接地导致了用户体验设计的重要性不断提升.与此同时,过去的流程冗长的设计开发模式已经不能够满足快速迭代的需要.<敏捷宣言> ...

  3. 12月6日 被引入的jsp 页面,引入 js 要注意结束符 要用 </script> 而不是 />

    12月6日  被引入的jsp 页面,引入 js 要注意结束符 要用  </script> 而不是 />

  4. 2018.09.12 poj2376Cleaning Shifts(线段树+简单dp)

    传送门 貌似贪心能过啊%%%. 本蒟蒻写的线段树优化dp. 式子很好推啊. f[i]表示覆盖1~i所需的最小代价. 那么显然对于一个区间[li,ri]" role="present ...

  5. bootstrap-treeview的 简单使用

    理论:http://blog.csdn.net/babyxue/article/details/73835444 插依赖Bootstrap 和jQuery <link href="~/ ...

  6. Java 增强 for 循环

    Java 增强 for 循环 Java5 引入了一种主要用于数组的增强型 for 循环. Java 增强 for 循环语法格式如下: for(声明语句 : 表达式) { //代码句子 } 声明语句:声 ...

  7. Java 窗体居中 通用代码

    Toolkit kit = Toolkit.getDefaultToolkit();    // 定义工具包    Dimension screenSize = kit.getScreenSize() ...

  8. Sensor Fusion-based Exploration in Home Environments using Information, Driving and Localization Gains(基于传感器融合的使用信息、驾驶和定位增益在家庭环境中的探索)

    Authors: Joong-Tae Park, Jae-Bok Song Department:Department  of  Mechanical  Engineering,  Korea  Un ...

  9. (并查集 添加关系)How Many Answers Are Wrong --Hdu --3038

    链接: http://acm.hdu.edu.cn/showproblem.php?pid=3038 http://acm.hust.edu.cn/vjudge/contest/view.action ...

  10. 日志记录的作用和方法 java

    程序中记录日志一般有两个目的:Troubleshooting和显示程序运行状态.好的日志记录方式可以提供我们足够多定位问题的依据.日志记录大家都会认为简单,但如何通过日志可以高效定位问题并不是简单的事 ...