C语言参数传递(值传递、地址传递)+二级指针
参数传递
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语言参数传递(值传递、地址传递)+二级指针的更多相关文章
- C语言提高 (3) 第三天 二级指针的三种模型 栈上指针数组、栈上二维数组、堆上开辟空间
1 作业讲解 指针间接操作的三个必要条件 两个变量 其中一个是指针 建立关联:用一个指针指向另一个地址 * 简述sizeof和strlen的区别 strlen求字符串长度,字符数组到’\0’就结束 s ...
- C语言复习---二维数组和二级指针的关系:没关系,别瞎想(重点)
前提:一维数组和一维指针为什么可以替换使用? ] = { , , }; int *p = a; ; i < ; i++) printf("%d ", *(p + i)); 上 ...
- C语言 值传递和地址传递
不少同学在学到C语言的指针部分时感到很困惑,对经常提到的"值传递"和"地址传递"两个概念弄不 明白.实际上,因为地址本身也可以作为一个特殊的"值&qu ...
- (C++)函数参数传递中的一级指针和二级指针
主要内容: 1.一级指针和二级指针 2.函数指针传递的例子 3.什么时候需要传递二级指针? 4.二级指针在链表中的使用 1.一级指针和二级指针 一级指针:即我们一般说的指针,就是内存地址: 二级指针: ...
- C语言指针系列 - 一级指针.一维数组,二级指针,二维数组,指针数组,数组指针,函数指针,指针函数
1. 数组名 C语言中的数组名是一个特殊的存在, 从本质上来讲, 数组名是一个地址, 我们可以打印一个指针的值,和打印一个数组的值来观察出这个本质: int nArray[10] ={ 0 }; in ...
- C 真正理解二级指针
本文转载自CSDN博主liaoxinmeng,做数据结构时遇到指针方面的问题,想了许久,因此我觉得很有必要复习一下二级指针及其使用 正文如下: 指针是C语言的灵魂,我想对于一级指针大家应该都很熟悉,也 ...
- C++ 二级指针与 const 关键字
可用七种不同的方式将 const 关键字用于二级指针,如下所示: //方式一:所指一级指针指向的数据为常量,以下几种为等效表示 const int ** pptc; //方式一 int const * ...
- C语言:值传递,地址传递和引用传递(example:值交换)
于C语言中值传递.地址传递和引用传递的我个人理解. 通过一个例子:swap(交换两个整型变量的值)来表现! #include <stdio.h> void swap1(int* a,int ...
- go语言基础之结构体做函数参数 值传递和地址传递
1.结构体做函数参数值传递 示例: package main //必须有个main包 import "fmt" //定义一个结构体类型 type Student struct { ...
随机推荐
- 判断浏览器是ie9座特殊处理
function ie(){ var agent = navigator.userAgent.toLowerCase();//判断浏览器版本 return (!!window.ActiveXObjec ...
- 日期处理相关 - “Fri Dec 11 00:00:00 CST 2015”日期格式解析
1.后台处理方式: /* 精简版解析 - 推荐 */ String a= "Fri Dec 11 00:00:00 CST 2015"; Date d = new Date(a); ...
- div添加滚动条常见属性
由于页面上的表里的末一列的内容太多,显示的内容不美观了,就想在这一列上加滚动条,在网上搜了一下,用div可以实现,感觉还不错,下面的是在网上查到的. 想在div里添加滚动条设置一下style就ok了 ...
- 类里面的非static const成员
类里面的成员变量可以用const修饰,在只用const不用static修饰的情况下,这种使用的限制比较多 (1)不能定义处初始化,必须在类的构造函数初始化列表里面初始化(虽然在vs中,可以在定义处初始 ...
- Tomcat之Windows环境下配置多个服务器
在应对多项目多端口的情况配置一个服务器是远不能满足开发条件的.例如微信公众号回调域名只接受80端口,而其他项目一般为默认的8080或者自定义的其他的端口. 废话多说,直入主题 准备条件:tomcat文 ...
- 2018.09.15 vijos1053Easy sssp(最短路)
传送门 貌似可以最短路时同时判定负环啊. 但我不想这样做. 于是写了一个dfs版的判环,bfs版的求最短路. 代码: #include<iostream> #include<ccty ...
- 2018.07.08 NOIP模拟 好数(线段树)
好数 题目背景 SOURCE:NOIP2016-AHSDFZ T3 题目描述 我们定义一个非负整数是"好数",当且仅当它符合以下条件之一: 1. 这个数是 0 或 1 . 2. 所 ...
- foreach循环赋值问题
foreach ($list as $key=>$val){ $data=array();//这一个一定要加上不然循环后,modify_one,modify_two都会赋值 if ($val[' ...
- python面向对象-4类的继承与方法的重载
1.类的继承与方法的重载 上面就是先定义了一个类A,然后由定义了一个类B,B继承了类A,这样B就有了A的非私有属性和方法. class Washer: company='ZBL' def __init ...
- vue实现消息的无缝滚动效果
export default { data() { return { animate:false, items:[ {name:"马云"}, {name:"雷军" ...