第1篇文章
最近笔者在学习Zed A. Shaw写的《“笨办法”学c语言》,但在处理函数形参是值或指针时,显得有点力不从心。故在查询资料后,将学习所得记录下来,以便加深记忆。
示例代码↓
// 函数的传值与传址示例代码
#include<stdio.h>
// 函数声明,exchange交换函数
void exchange_value(int a,int b); // 传值
void exchange_pointer(int *a,int *b); // 传址
int main(int argc,char *argv[])
{
int x = 10;
int y = 2;
printf("NO.1: x=%d,y=%d\n",x,y);
exchange_value(x,y);
printf("NO.2: x=%d,y=%d\n",x,y);
exchange_pointer(&x,&y);
printf("NO.2: x=%d,y=%d\n",x,y);
return 0;
}
// 函数实现
void exchange_value(int a,int b)
{
int temp = a;
a = b;
b = temp;
}
void exchange_pointer(int *a,int *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
运行结果如下:
exchange_value函数没有效果,而exchange_pointer成功交换了x和y。
笔者理解如下:
调用(被调)函数时,函数形参将获得实参值的一份拷贝,即传值:a = 10,b = 2,传址:a = 储存 x 的地址, b = 储存 y 的地址。因为形参的值是拷贝来的,所以被调函数对拷贝数据的任何操作都不会影响主调函数中的实参的值。下面针对两种方式分别来讨论。
- exchange_value:形参 a,b 分别被赋值为10,2 ,函数体内的操作与主调函数无关。这就如同(不太准确 :)又写了一个main()函数,并定义了a,b两个整数型变量,所以任何操作都不影响主调函数中变量的值。
- exchange_pointer:形参 a,b 分别被赋值为储存 x 的地址和储存 y 的地址,同样函数体内的操作与主调函数无关,但这个略有不同。首先假设储存x的地址为100(实际地址不会如此简单),储存y的地址为104,如表1.1。
将参数传递给exchange_pointer后,如表1.2表1.1初始状态 内存地址 &x——100 &y——104 内存储存的值 10 2
*a 即访问a所储存的内存地址的值,所以「int temp = *a;*a = *b;*b = temp;」 实际上是将a所储存的地址指向的值与b所储存的地址指向的值交换。如表1.3表1.2 内存地址 a = &x——100 b = &y——104 内存储存的值 10 2
所以,主调函数再次调用x(即 *(&x) ,下同)和y时,值发生改变。表1.3最终状态 内存地址 a = &x——100 b = &y——104 内存储存的值 2 100
总结:传值不改变主调函数中变量的值,传址通过间接访问操作(*)改变储存在相应内存地址的值来修改主调函数中变量的值。
-完- 2018.10.5
参考书籍:
[1].《c和指针》-Kenneth A. Reek,人民邮电出版社
[2]. 《C Primer Plus 中文版(第6版)》- Stephen Prata,人民邮电出版社