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

参数传递

C语言参数传递一般分为:值传递和地址传递

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

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

值传递:

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

 1 #include <stdio.h>
 2
 3 void swap(int x, int y);
 4
 5 main()
 6 {
 7     int a = 10, b = 20;
 8
 9     swap(a, b);
10     printf("a=%d\nb=%d\n", a, b);
11
12     return 0;
13 }
14 void swap(int x, int y)
15 {
16     int t;
17
18     t = x;
19     x = y;
20     y = t;
21 }

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

地址传递:

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

 1 #include <stdio.h>
 2
 3 void swap(int *x, int *y);
 4
 5 main()
 6 {
 7     int a = 10, b = 20;
 8
 9     swap(&a, &b);
10     printf("a=%d\nb=%d\n", a, b);
11
12     return 0;
13 }
14 void swap(int *x, int *y)
15 {
16     int t;
17
18     t = *x;
19     *x = *y;
20     *y = t;
21 }

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

易错点补充:

 1 #include <stdio.h>
 2
 3 void swap(int *x, int *y);
 4
 5 main()
 6 {
 7     int a = 10, b = 20;
 8     int *pp = &a;
 9     int *kk = &b;
10     swap(pp, kk);
11     printf("a=%d\nb=%d\n", *pp, *kk);
12
13     return 0;
14 }
15 void swap(int *x, int *y)
16 {
17     int *t;
18
19     t = x;
20     x = y;
21     y = t;
22 }

请读者想一下,上述代码执行后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的值(这里与值传递相似)

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

 1 #include <stdio.h>
 2
 3 void swap(int *x, int *y);
 4
 5 main()
 6 {
 7     int a = 10, b = 20;
 8     int *pp = &a;
 9     int *kk = &b;
10
11     printf("a的地址%p----b的地址%p\n\n", &a, &b);
12     printf("pp的值%p----kk的值%p\n", pp, kk);
13     printf("pp的地址%p----kk的地址%p\n\n", &pp, &kk);
14     swap(pp, kk);
15     printf("a = %d\nb = %d", *pp, *kk);
16
17     return 0;
18 }
19 void swap(int *x, int *y)
20 {
21     int *t;
22
23     printf("x的值%p----y的值%p\n", x, y);
24     printf("x的地址%p----y的地址%p\n", &x, &y);
25
26     t = x;
27     x = y;
28     y = t;
29 }

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

(灵魂画手已上线)

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

 1 #include <stdio.h>
 2
 3 void swap(int *x, int *y);
 4
 5 main()
 6 {
 7     int a = 10, b = 20;
 8     int *pp = &a;
 9     int *kk = &b;
10
11     swap(pp, kk);
12     printf("a = %d\nb = %d", *pp, *kk);
13
14     return 0;
15 }
16 void swap(int *x, int *y)
17 {
18     int t;
19
20     t = *x;
21     *x = *y;
22     *y = t;
23 }

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

(灵魂画手已经上线)

二级指针

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

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

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

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

 1 #include <stdio.h>
 2
 3 void swap(int **x, int **y);
 4
 5 main()
 6 {
 7     int a = 10, b = 20;
 8     int *pp = &a;
 9     int *kk = &b;
10
11     swap(&pp, &kk);
12     printf("a = %d\nb = %d", *pp, *kk);
13
14     return 0;
15 }
16 void swap(int **x, int **y)
17 {
18     int t;
19
20     t = **x;
21     **x = **y;
22     **y = t;
23 }

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

 1 #include <stdio.h>
 2
 3 void swap(int **x, int **y);
 4
 5 main()
 6 {
 7     int a = 10, b = 20;
 8     int *pp = &a;
 9     int *kk = &b;
10
11     swap(&pp, &kk);
12     printf("a = %d\nb = %d", *pp, *kk);
13
14     return 0;
15 }
16 void swap(int **x, int **y)
17 {
18     int *t;
19
20     t = *x;
21     *x = *y;
22     *y = t;
23 }

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

下面是二级指针示意图

(灵魂画手已上线)

若有疑问,欢迎留言

原文地址:https://www.cnblogs.com/lanhaicode/p/10342932.html

时间: 02-02

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

对几种传递的理解:值传递,地址传递,引用传递

对几种传递的理解:值传递,地址传递,引用传递 因为会用到形参和实参的概念,区别一下,形参 即在定义函数时 int add(int a , int b)中a,b,即为形参.而当调用时int(3,4)中3,4即为实参. ①值传递 #include<stdio.h> void Exchg1(int x, int y){ int tmp; tmp=x; x=y; y=tmp; printf("x= %d , y= %d\n",x,y);}int main(){ int a=4,b=

二级指针与二维数组

最近看<Linux C程序设计大全>这本书,虽然书中有一些错误,但整体来说,书写得还算可以. 当看到网络编程[第23.2.4小节 获得主机信息]时,遇到了一段代码,原文如下: “一台主机有许多和网络相关的信息,例如,主机名称.IP地址.主机提供的服务等.这些信息一般都保存在系统中的某个文件里(例如/etc/hosts等),用户程序可以通过系统提供的函数读取这些文件上的内容.Linux环境下使用gethostent函数读取和主机有关的信息,该函数的原型如下: 1 #include <net

c++中的悬浮指针和野指针 二级指针

(1) c++中的悬浮指针:声明了但没有被付值的指针,它指向内存中的任意一个空间.避免悬浮指针的一个方法是开始就付值为NULL (2)"野指针"不是NULL指针,是指向"垃圾"内存的指针.人们一般不会错用NULL指针,因为用if语句很容易判断.但是"野指针"是很危险的,if语句对它不起作用.野指针的成因主要有两种: 一.指针变量没有被初始化.任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的,它会乱指一气.所以,指针变量在创建的同

二级指针的形参问题

草草嗒!下面的程序myMalloc是没有返回值的!害我想半天=.= 用一级指针同样可以实现程序2,但需要返回值. 总结:二级指针做形参时,操作的对象已经不是临时变量了:而一级指针操作的是临时变量. ====下面的已经没价值了=============================== 程序1:  void  myMalloc(char  *s)  //我想在函数中分配内存,再返回  {       s=(char  *)  malloc(100);  }   void  main()  {  

java中参数传递--值传递,引用传递

java中的参数传递--值传递.引用传递 参数是按值而不是按引用传递的说明 Java 应用程序有且仅有的一种参数传递机制,即按值传递. 在 Java 应用程序中永远不会传递对象,而只传递对象引用.因此是按引用传递对象.Java 应用程序按引用传递对象这一事实并不意味着 Java 应用程序按引用传递参数.参数可以是对象引用,而 Java 应用程序是按值传递对象引用的. Java 应用程序中的变量可以为以下两种类型之一:引用类型或基本类型.当作为参数传递给一个方法时,处理这两种类型的方式是相同的.两

java值和地址值传递、字符串常量池的理解

#java值和地址值传递的理解: - 基本数据类型和基本数据类型的封装类都是:值传递 * 形式参数的改变不会影响实际参数的改变(相当于将值复制一份传递给形参,自身没做任何改变) - 引用数据类型都是 地址值传递 * 形式参数的改变会影响实际参数的改变(将地址值赋值给形参,形参就可以指向实参所指向的地址, 即形参也可以操作实参指向地址的数据了) #注意:String是个特例(当作基本类型处理) - 分析:从String类的源码可以知道,String相当于是char[]的封装类,即具有char类型的

转:Web页面通过URL地址传递参数常见问题及检测方法

Web页面即我们在浏览器中所看到的网页,在Web应用程序中,其页面往往需要进行动态切换和数据交互,页面间的数据常规传递方法有多种,本文主要介绍Web页面处理程序中常见的URL地址参数传递方法,包括概述其实现原理.特点和常见问题,最后介绍检测该方式常见应用问题的测试思路和方法. 1.web页面的概念 Web是internet上一个非常重要的资源信息网,产生于20世纪90年代初,它遵循超文本传输协议,以超文本或超媒介的形式传送各种各样的信息,为用户提供了一个具有友好的图形化界面--Web页面,以便用

JavaScript中函数参数的按值传递与按引用传递(即按地址传递)

首先声明一句:JavaScript中所有函数的参数都是按值传递的!不存在按引用传递! 在讲传递参数之前我们先来讲一下指针. 学过C指针的应该都知道,指针变量中保存的是一个地址,程序可以根据所保存的地址访问内存中对应的值并进行操作,如下图: 其中地址为0x00000016保存的是一个地址,指向地址0x00000036,即0x00000016被开辟为一个指针变量,可以引用0x00000036地址的值,这是按引用方式访问变量:另外一种访问变量的方式是按值访问,即图中0x00000008地址. 在Jav

值传递 引用传递

方法参数传递有2种方式: 值传递和引用传递. 值传递: 默认都是值传递.值传递有2种,值类型和引用类型的.实质是复制栈中的值. 值类型的值传递:栈中的值就是实际值. 引用类型的值传递:栈中的值是内存堆中地址. 引用传递: 参数前加ref的为引用传递,引用传递有2种,值类型和引用类型的.实质就是传递自己本身,只是多了个别名.

Android技术10:Java与C语言之间简单数据的传递

由于C语言和Java语言之间很多类型不一致性,因此使用native时,需要数据类型转换.下面演示分别传递整型,字符串,整型数组,Java静态方法传递数据. 1.创建native方法 我们单独创建一个NativeClass类来存放native方法 1 package com.forsta.ndk; 2 3 public class NativeClass { 4 public native int add(int x,int y); 5 public native String showStrin