您的位置:首页 > 编程语言 > C语言/C++

[原创]详细讲解C/C++中的函数中的传值与传址

2009-10-04 17:17 197 查看
学习C语言快有8个月了,目前正在学习C++和数据结构。记得刚开始学习函数传值与传址时一直没弄懂二者区别,之前在别人的csdn博客里看到过别人关于传值传址的讲解,感觉文章并没有进行实质性地对二者进行详解,反正我看的是稀里糊涂.而前段时间看<<面向对象程序设计——C++语言描述>>时,上面有一句类似的话:对于f( int x )传入的x只是x的一个拷贝而不是x本身感触颇深! 经过本人努力测试终于基本上掌握了传值与传址的区别,我的结论是基于测试得来的,不是从书上copy下来的,所以有些是个人理解,不具权威性,希望对大家有所帮助,不管对与不对,我只是希望可以帮助大家,欢迎各位拍砖.不过在通过实例来说明之前还是要说几个知识点的:

1.关于变量:

变量实质是存储单元

个人认为变量有3个要素:

变量名(用来标识一个存储单元),变量的地址(存储单元的地址),变量的值(存储单元的内容)

变量的值是无法惟一确定一个变量的,因为不同的变量可以有相同的值,在c语言中变量名应该可以确定一个变量,而在C++中一个变量可以有多个变量名,称之为一个变量的引用,int x,& y=x;这里&表示y是引用类型,即是变量x的别名,因此要注意x与y实际是同一个存储单元!最后说一下变量的地址,变量一经定义,则系统会为其开辟内存空间,即变量的地址是不变的!由此可见地址是标识变量的最准确的方式,因为一个地址与一个存储单元是一一对应的!所以通过地址来对存储单元的内容进行操作能够实现对存储单元本身操作,而这种方式看起来效率很低但是当把他应用到非主函数(main())中的形参时内存开销会变小,因为一个struct可以被一个unsigned int(地址就是一个unsigned int)标识,这就是C/C++引入指针的原因吧!

2.再论指针

指针是一种数据类型,指针变量的值是地址,指针是变量,所以指针也有地址.对于一个已定义的变量其地址是不变的,而指针的值是地址,指针的值是可变的,亦即指针可以指向任意一个其可以指向的变量!所以指针用起来是很灵活的,想要掌握指针必须多编程,这里不再探讨指针过多的问题.

3.函数中的局部变量(这里函数不包括主函数( main() ) )

函数中的变量是局部变量,当函数调用结束后原函数定义的变量将不存在,即所占的存储空间会被释放.注意形参同样是局部变量f( int x , int* p );中x与p都是局部变量,当你执行语句f( a , &a );时一定要注意函数中的 x不是a , p也不是&a,意思是调用时只是进行简单的赋值操作,即x=a,p=&a;因此x与a的值相同但二者地址不同亦即x与a不是同一个存储单元!指针类型的p也不例外,p只是&x的一个拷贝,而非&x本身!因此改变p是改变不了&x的(当然&x本身是不可以改变的),但是通过*p=9;这种方式却可以改变x,你知道是为什么吗?

废话不说了,下面直接用实例来证明:

C/C++ Code:

#include <stdio.h>

void passByValue( int Vx )/* Vx只是变量x的一个拷贝,或者说只是变量x的一个副本,而不是变量x本身! */
{
Vx = 2 ;/*改变的是变量名为Vx的存储单元的值,而不是变量名为x的存储单元的值,亦即改变的不是x本身的值!*/
printf("In function /"passByValue( int Vx )/":/n");
printf(" Vx = %d , &Vx = %#x/n",Vx,&Vx);/*输出变量名为Vx的存储单元的值和地址*/
}

void passByAddress( int* Ax )/* Ax只是&x的一个拷贝,而非&x本身*/
{
int temp_Ax=3;
Ax=&temp_Ax;/* Ax不再指向x,Ax指向temp_Ax */
printf("In fuuction /"passByAddress( int* Ax )/":/n");
printf("*Ax = %d , Ax  = %#x/n",*Ax,Ax);/*输出Ax的值和地址为Ax的存储单元的值*Ax,即temp_Ax*/
}

void passByPointer( int* Px )/* Px只是&x的一个拷贝,而非&x本身 */
{
*Px=4;/*改变地址为Px的存储单元的值为4,而地址为Px的存储单元就是x本身,因此*Px=4;改变的是x本身的值!*/
printf("In fuuction /"passByPointer( int* Px )/":/n");
printf("*Px = %d , Px  = %#x/n",*Px,Px);/*输出Px的值和地址为Px的存储单元的值*Px,即x*/
}

void passByReference( int& Rx )/* Rx只是变量x的一个引用,Rx与x标识的是同一个存储单元*/
{
Rx = 5 ;/*虽然变量名不同,但改变Rx实质是改变x,因为变量名为x的存储单元就是变量名为Rx的存储单元*/
printf("In fuuction /"passByReference( int& Rx )/":/n");
printf("Rx  = %d , &Rx = %#x/n",Rx,&Rx);/*输出变量x的引用Rx的值和地址,即x的值和地址*/
}

int main()
{
int x = 0 , y = 1 ;

/* &x = &y;     Line 36: error: passMethod.cpp non-lvalue in assignment */
/*上式说明在程序的一次执行中&x是一个常量指针(const *),&x指向x并且&x不可变,
这里即便x是指针变量也不例外,变量x一经定义,则系统自动会为变量x分配内存空间,
因此&x不可变,但是指向x的指针Px=&x是可变的,因为Px还可以指向y,即Px=&y*/

printf("Original x and &x:/n  x = %d , &x  = %#x/n/n",x,&x);

passByValue( x );
printf("After reallocate function /"passByValue( x )/":/n");
printf("In function /"main( )/":/n  x = %d , &x  = %#x/n/n",x,&x);/*无法改变x的值*/
/*两个函数中&Vx与&x不同,说明Vx并不是x本身!*/
/*注意:函数中对于传值(非指针),函数改变的是X的一个拷贝,即Vx,而不是变量x本身的值!*/

passByAddress( &x );
printf("After reallocate function /"passByAddress( &x )/":/n");
printf("In function /"main( )/":/n  x = %d , &x  = %#x/n/n",x,&x);/*无法改变x的值*/
/*两个函数中Ax与&x不同,说明Ax不再指向x!*/
/*注意:函数中对于传地址,改变Ax不能改变x的值,因为一旦改变Ax,则Ax不再指向x,那么
一切的操作都将与x无关!*/

passByPointer( &x );
printf("After reallocate function /"passByPointer( &x )/":/n");
printf("In function /"main( )/":/n  x = %d , &x  = %#x/n/n",x,&x);/*可以改变x的值*/
/*两个函数中Px与&x相同,说明Px指向x!*/
/*注意:函数中对于传地址,改变*Px的值实质就是改变x,因为Px指向x,注意改变x的值的方式!*/

passByReference( x );
printf("After reallocate function /"passByReferemce( x )/":/n");
printf("In function /"main( )/":/n  x = %d , &x  = %#x/n",x,&x);/*可以改变x的值*/
/*两个函数中&Rx与&x相同,说明Rx与x标识的是同一个存储单元!*/
/*注意:函数中改变Rx实质就是改变x本身,因为Rx与x是同一个存储单元的不同标识!*/

return 0;
}


这里给出运行结果:(不含/*...*/及其中的部分)

Original x and &x:
x = 0 , &x = 0x22ff74 /* x的值和地址 */

In function "passByValue( int Vx )":
Vx = 2 , &Vx = 0x22ff50

After reallocate function "passByValue( x )":
In function "main( )":
x = 0 , &x = 0x22ff74 /* &Vx与&x不相等 Vx与x也不相等 */

In fuuction "passByAddress( int* Ax )":
*Ax = 3 , Ax = 0x22ff44
After reallocate function "passByAddress( &x )":
In function "main( )":
x = 0 , &x = 0x22ff74 /* Ax与&x不相等 *Ax与x也不相等 */

In fuuction "passByPointer( int* Px )":
*Px = 4 , Px = 0x22ff74
After reallocate function "passByPointer( &x )":
In function "main( )":
x = 4 , &x = 0x22ff74 /* Px与&x相等 *Px与x相等 */

In fuuction "passByReference( int& Rx )":
Rx = 5 , &Rx = 0x22ff74
After reallocate function "passByReferemce( x )":
In function "main( )":
x = 5 , &x = 0x22ff74 /* &Rx与&x相等 Rx与x相等 */

由此可以知道传值与传址实质都是传值,地址也是值,地址是指针的值!关键是看你要改变变量的哪个部分或者说你要引用变量的哪个部分,即通过何种方式去引用变量?一定要弄清变量的值与地址的关系,这样才能灵活地运用指针!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: