解析C/C++值传递和址传递的区别

C/C++的按值传递和按地址传递有明显不同,下面对他们作个区别:

按值传递:在调用函数中将原函数的值拷贝一份过去被调用的函数,在被调用函数中对该值的修改不会影响原函数的值。

按地址传递:在调用函数的时候将原函数的值所在的地址拷贝一份过去,被调用函数对这个地址所作的修改会影响原来的值。

概述:

首先我们要知道 a的地址”和“a地址中的内容”的区别,数据是存放在内存中的,每一个变量都有一个内存地址, 变量的内容存放在对应内存地址的空间中

比方说定义

int a = 10;

那么a在内存中的地址是0x1100,在这个地址中存储的数据是10

假设创建指针p,把a的地址赋值给p,就是把a的首地址0x1100赋值给指针p,这个时候p的值就是变量a在内存中的首地址

int a =10;
int*p;
p=&a; //把a的首地址赋值给P

简单点的理解就好比你去图书馆借书,每本书都会有他的一个编号(地址),记录它所在的位置,而这个书,就是这个地址对应的内容
如果你用指针,得到的是这个书所对应的编号(地址) ,存储内容就是地址
如果你是变量赋值,值传递,那么就相当于复印了一遍这个书(地址对应的内容),然后用一个新的编号(地址),去存储你复印的这本书

从命名来理解

所以我们就会发现:

值传递,或者变量赋值,修改变量的值,修改的是新的新的编号(地址)中的内容(复印的书),不会影响到原来编号(地址)中的数据。

也就是形参是实参内容的拷贝,并不是地址的拷贝,所以改变形参的值并不会影响实参的值

使用址传递,用指针修改变量的值,就是把原编号(地址)中的书给修改了,换了一本新的书,就相当于对实参本身进行的操作。

声明Declaration:描述在其他地方创建的对象,并不分配内存。(可以出现在多个地方)

定义Definition:产生一个新的对象,并分配内存。(只能出现一次)

值传递

新开辟一个内存空间,存储原来变量的值,修改变量修改的是新的内存空间中的值。所以,原始的参数不会被函数修改。

值传递的优点: 通过值来传递的参数可以是数字,变量,表达式。原本参数的值不会被修改。

值传递的缺点: 不能修改原参数的值。

#include <stdio.h>

void swap (int x, int y)
{
	int temp;
	temp = x;
	x = y;
	y = temp;
//	printf ("x = %d, y = %d\n", x, y);
}

int main (void)
{
	int a = 4, b = 6;
	printf ("交换前:\n a = %d, b = %d\n", a, b);
	swap (a, b);
	printf ("交换后:\n a = %d, b = %d\n", a, b);
	return 0;
}

输出:

址传递

址传递就是指针传递,形参实际是指向实参地址的指针,当对形参的进行操作时,就相当于对实参本身进行的操作,可以改变指针指向内容的值,但是不能改变指针本身的地址。

#include <stdio.h>
void swap (int *x, int *y)
{
	int temp=*x;
	*x=*y;
	*y=temp;
	//printf("x = %d, y = %d\n", *x, *y);
}

int main(void)
{
	int a=4;
	int b=6;
    printf("交换前:\n a = %d, b = %d\n", a, b);
	swap (&a,&b);  //传递的是地址
	printf("交换后:\n a = %d, b = %d\n", a, b);
	return 0;
}

在你了解了什么是值传递和址传递之后,我们来看一个面试题:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void GetMemory( char *p ) {
	p = (char *) malloc( 100 );
}

int main (void) {
	char *str = NULL;
	GetMemory( str );
	strcpy( str, "hello world" );
	printf( str );
	return 0;
}

请问运行会有什么样的结果? 会输出hello world吗?

答:程序崩溃,没有输出

因为 GetMemory 并不能传递动态内存,Test 函数中的 str 一直都是 NULL。strcpy(str, “hello world”);将使程序崩溃
函数中的p其实是实参str的一份拷贝,函数中的操作都是对q进行的,str仍然是NULL,所以输出*str的值产生崩溃

也就是:传递给形参的指针仍然是实参指针的一份拷贝

这一点需要注意

解决的话可以把形参改为二重指针,程序便可以按预想中的情形进行:

二重指针指向一重指针的地址 也就是传递过来的实际是*str的参数本身

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void GetMemory( char **p ) {
	*p = (char *) malloc( 100 );
}

int main (void) {

	char *str = NULL;
	GetMemory(&str);
	strcpy( str, "hello world" );
	printf( str );
	return 0;
}

到此这篇关于解析C/C++值传递和址传递的区别的文章就介绍到这了,更多相关C/C++值传递和址传递内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • java及C++中传值传递、引用传递和指针方式的理解

    java的值传递理解: 代码1: public class Test { /** * @param args */ public static void main(String[] args) { StringBuffer buffer= new StringBuffer("colin"); SChange(buffer); System.out.println( buffer); } public static void SChange (StringBuffer str) { st

  • C++小知识:C/C++中不要按值传递数组

    错误的代码: ID_INLINE mat3_t::mat3_t( float src[ 3 ][ 3 ] ) { memcpy( mat, src, sizeof( src ) ); } 说明: 有时候程序员会忘记 C/C++ 里数组不能按值传递给函数.当你试图这样做时,是数组的指针(第一个元素的地址)而不是整个数组被传递.我们还应该记住,方括号中的数字没有任何意义.它们仅仅是程序员所做的标志,记录了传递数组的『假定』大小.事实上,你也可以传递一个大小完全不同的数组.例如,下面的代码就会成功编译

  • 解析C/C++值传递和址传递的区别

    C/C++的按值传递和按地址传递有明显不同,下面对他们作个区别: 按值传递:在调用函数中将原函数的值拷贝一份过去被调用的函数,在被调用函数中对该值的修改不会影响原函数的值. 按地址传递:在调用函数的时候将原函数的值所在的地址拷贝一份过去,被调用函数对这个地址所作的修改会影响原来的值. 概述: 首先我们要知道 "a的地址"和"a地址中的内容"的区别,数据是存放在内存中的,每一个变量都有一个内存地址, 变量的内容存放在对应内存地址的空间中 比方说定义 int a = 1

  • 浅谈Java中真的只有值传递么

    回顾值传递和引用传递 关于Java是值传递还是引用传递,网上有不一样的说法. 1.基本类型或基本类型的包装类以及String是值传递,引用类型是引用传递. 2.Java中只有值传递. 关于这个问题应该是存在争议的.根据测试出来的结果和我们自己的经验,以及口口相传或是上学时老师讲的,我们认为是第一种.但第二种说法的呼声也很高,渐渐地我们也认为第2中才是对的.那么下面我们就来分析一下这个问题. 在谈这个问题之前我们先了解值传递和引用传递的概念及现象.我还记得,值传递和引用传递这些概念是大学里学Jav

  • C#中的值传递和引用传递详细解析

    一.传递参数既可以通过值也可以通过引用传递参数.通过引用传递参数允许函数成员(方法.属性.索引器.运算符和构造函数)更改参数的值,并保持该更改. 二.传递值类型参数值类型变量直接包含其数据,这与引用类型变量不同,后者包含对其数据的引用.因此,向方法传递值类型变量意味着向方法传递变量的一个副本.方法内发生的对参数的更改对该变量中存储的原始数据无任何影响.如果希望所调用的方法更改参数的值,必须使用 ref 或 out 关键字通过引用传递该参数.为了简单起见,下面的示例使用 ref. 1. 通过值传递

  • Java按值传递和按址传递(面试常见)

    先复制一个面试/笔试的题: 当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递? 答案: 是值传递.Java语言的方法调用只支持参数的值传递.当一个对象实例作为一个参数被传递到方法中时,参数的值就是对该对象的引用.对象的属性可以在被调用过程中被改变,但对对象引用的改变是不会影响到调用者的.C++和C#中可以通过传引用或传输出参数来改变传入的参数的值.在C#中可以编写如下所示的代码,但是在Java中却做不到. java中的按值传

  • 浅谈JavaScript 函数参数传递到底是值传递还是引用传递

    在传统的观念里,都认为JavaScript函数传递的是引用传递(也称之为指针传递),也有人认为是值传递和引用传递都具备.那么JS的参数传递到底是怎么回事呢?事实上以下的演示也完全可以用于Java 首先来一个比较简单的,基本类型的传递: function add(num){ num+=10; return num; } num=10; alert(add(num)); aelrt(num); //输出20,10 对于这里的输出20,10,按照JS的官方解释就是在基本类型参数传递的时候,做了一件复制

  • 深入了解为什么Java中只有值传递?

    1.为什么 Java 中只有值传递? 首先回顾一下在程序设计语言中有关将参数传递给方法(或函数)的一些专业术语.按值调用(call by value)表示方法接收的是调用者提供的值,而按引用调用(call by reference)表示方法接收的是调用者提供的变量地址.一个方法可以修改传递引用所对应的变量值,而不能修改传递值调用所对应的变量值. 它用来描述各种程序设计语言(不只是Java)中方法参数传递方式. Java程序设计语言总是采用按值调用.也就是说,方法得到的是所有参数值的一个拷贝,也就

  • 一文秒懂java到底是值传递还是引用传递

    首先回顾一下在程序设计语言中有关将参数传递给方法(或函数)的一些专业术语.按值调用(call by value)表示方法接收的是调用者提供的值,而按引用调用(call by reference)表示方法接收的是调用者提供的变量地址.一个方法可以修改传递引用所对应的变量值,而不能修改传递值调用所对应的变量值. 它用来描述各种程序设计语言(不只是 Java)中方法参数传递方式. Java 程序设计语言总是采用按值调用.也就是说,方法得到的是所有参数值的一个拷贝,也就是说,方法不能修改传递给它的任何参

  • 浅谈从Java中的栈和堆,进而衍生到值传递

    简述Java中的栈和堆,变量和对象的地址存放和绑定机制 初学java的小白,很多人都搞不清楚java中堆和栈的概念,我们都知道计算机只能识别二进制字节码文件,如果分不清楚对象和变量在内存的地址分配,也就是堆和栈的问题,很多问题比如绑定机制.静态方法.实例方法.局部变量的作用域就会搞不清楚. 首先记住结论: 基本数据类型.局部变量.String类型的直接赋值都是存放在栈内存中的,用完就消失. new创建的实例化对象.String类型的构造方法new出来的对象及数组,是存放在堆内存中的,用完之后靠垃

  • 全面理解Java中的引用传递和值传递

    目录 1.基本类型和引用类型在内存中的保存 2.变量的基本类型和引用类型的区别 3.引用传递和值传递 4.结论 关于Java传参时是引用传递还是值传递,是一个讨论比较多的话题, 有说Java中只有值传递,也有些地方说引用传递和值传递都存在,本篇记录思考过程,不保证正确性, 感兴趣的同学一起讨论. 1.基本类型和引用类型在内存中的保存 Java中数据类型分为两大类,基本类型和对象类型.相应的,变量也有两种类型:基本类型和引用类型. 基本类型的变量保存原始值,即它代表的值就是数值本身: 而引用类型的

  • C语言值传递和地址传递详解

    目录 一. 值传递 二.地址传递 总结 一. 值传递 我们举一个例子: 写一个函数找出两个整数中的最大值. #include<stdio.h> //get_max函数 int get_max(int x,int y) { return (x>y)?x:y; } int main() { int num1 = 10; int num2 = 20; int max = get_max(num1,num2); printf("max = %d\n",max); return

随机推荐