C语言参数传递(值传递、地址传递)+二级指针

时间:2022-08-25 12:49:38

参数传递

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;
}

C语言参数传递(值传递、地址传递)+二级指针

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

C语言参数传递(值传递、地址传递)+二级指针

(灵魂画手已上线)

传入指针的值虽然不能对指针的值进行修改,但是可以通过地址直接对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;
}

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

C语言参数传递(值传递、地址传递)+二级指针

(灵魂画手已经上线)

二级指针

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

下面介绍第四种,传入指针的地址,上面第二种(传入变量的地址)和第三种(传入指针的值)传递方式使用的用来接收参数的形参都是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语言参数传递(值传递、地址传递)+二级指针的更多相关文章

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

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

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

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

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

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

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

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

  5. C语言指针系列 - 一级指针&period;一维数组&comma;二级指针&comma;二维数组&comma;指针数组&comma;数组指针&comma;函数指针&comma;指针函数

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

  6. C 真正理解二级指针

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

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

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

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

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

  9. 【转】【java】论integer是地址传递还是值传递

    转自:http://www.tuicool.com/articles/AraaQbZ 论integer是地址传递还是值传递 Integer 作为传参的时候是地址传递 , 可以参考如下例子,在程序刚启动 ...

随机推荐

  1. 怎么才能算大项目(Application),大的衡量?

    最近在思考一个问题,就是怎么才算一个大型项目,大的衡量有哪些东西?为什么要搞清这个问题呢,是因为在实际的开发过程中,如果知道这是个多大的项目,那就有各种相应的解决方案(我们称之为套路的东西)就可以使用 ...

  2. Chart系列(一):Chart的基本元素

    如何使用一个Chart,则首先必须要了解其组织结构,其次知道其API. Chart元素 首先,来看看Chart组成元素. Axis Label:坐标轴标签   Axis Title:坐标轴标题   C ...

  3. JavaEE基础(十一)&sol;Eclipse介绍

    1.Java开发工具(常见开发工具介绍) A:操作系统自带的记事本软件 B:高级记事本软件 C:集成开发环境 IDE (Integrated Development Environment) D:Ec ...

  4. AngularJS特性

    如果你不熟悉什么是Angular.js的话,小编我强烈推荐你阅读 Javascript教程:AngularJS的五个超酷特性.简单来说Angular.js是google开发者设计和开发的一套前端开发框 ...

  5. Agri-Net(prim算法,最小生成树问题)

    看图便知道: 来来上代码:         #include <cstdio>#include <cstdlib>#include <cstring>#includ ...

  6. maven&lowbar;基本配置

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/20 ...

  7. java实现https请求

    package com.lichmama.test; import java.io.IOException; import java.net.URL; import java.security.Key ...

  8. &period;Net Core2&period;0 &plus; Nginx &plus; CentOS 部署

    准备把项目往Linux上迁移,整个流程跑了一下,也遇到无数个坑...以下为亲测并修改后的完整流程... 安装ZIP yum install -y unzip zip Putty:WINDOWS上传文件 ...

  9. 知识点:tuple 元素真的不可变吗

    tuple 元素真的不可变吗 有一种有序列表叫元组:tuple. tuple和list非常类似,但是tuple一旦初始化就不能修改,比如同样是列出单位或同学的名字: >>> clas ...

  10. 解决本地文件上传时fakepath的问题

    $("input[type='file']").on('change', function () { var oFReader = new FileReader(); var fi ...