参数传递

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. PAT 1057 数零壹 (20)(代码+思路)

    1057 数零壹(20 分) 给定一串长度不超过 10​5​​ 的字符串,本题要求你将其中所有英文字母的序号(字母 a-z 对应序号 1-26,不分大小写)相加,得到整数 N,然后再分析一下 N 的二 ...

  2. chrome审查元素功能,web开发强大帮手

    怎样打开Chrome的开发者工具? 你可以直接在页面上点击右键,然后选择审查元素: 或者在Chrome的工具中找到: 或者,你直接记住这个快捷方式: Ctrl+Shift+I (或者Ctrl+Shif ...

  3. Devexpress VCL Build v2013 vol 14.1.3 发布

    我修,我修,修修修. New Major Features in 14.1 What's New in VCL Products 14.1 Breaking Changes To learn abou ...

  4. spring cloud--------------------HystrixCommand使用

    一.注解使用: (一)注解同步执行 1.注解开启断路器功能 @EnableCircuitBreaker 2.方法事例 @HystrixCommand(fallbackMethod = "er ...

  5. 【Unity】2.0 第2章 Unity编辑器和基本操作

    分类:Unity.C#.VS2015 创建日期:2016-03-26 本章要点: 1.掌握Unity 5.3.4编辑器视图和菜单项及其含义,这是入门的最基础部分,必须掌握. 2.了解最基本的操作,先学 ...

  6. MySQL外键使用及说明详解

    一.外键约束 MySQL通过外键约束来保证表与表之间的数据的完整性和准确性. 外键的使用条件: 1.两个表必须是InnoDB表,MyISAM表暂时不支持外键(据说以后的版本有可能支持,但至少目前不支持 ...

  7. HDU1459 非常可乐(BFS) 2016-07-24 15:00 165人阅读 评论(0) 收藏

    非常可乐 Problem Description 大家一定觉的运动以后喝可乐是一件很惬意的事情,但是seeyou却不这么认为.因为每次当seeyou买了可乐以后,阿牛就要求和seeyou一起分享这一瓶 ...

  8. Andfix热修复原理

    一.前言 最近腾讯弄出一个Tinker热修复框架,那么本文先不介绍这个框架,先来介绍一下阿里的一个热修复框架AndFix,这个框架出来已经很长时间了,但是看网上没有太多非常详细的讲解,这里就来做一次分 ...

  9. ESP32应用程序的内存布局

    应用程序内存布局 ESP32芯片具有灵活的内存映射功能.本节介绍ESP-IDF在默认情况下如何使用这些功能. ESP-IDF中的应用程序代码可以放置在以下内存区域之一中. IRAM(指令RAM) ES ...

  10. [Linux-vi] The simple set of vi command

    Source : https://www.cs.colostate.edu/helpdocs/vi.html What is vi? The default editor that comes wit ...