关于形参与实参 按值传递和按址传递一点总结

形参与实参:

如果把函数比喻成一台机器,那么参数就是原材料,返回值就是最终产品;从一定程度上讲,函数的作用就是根据不同的参数产生不同的返回值。
C语言函数的参数会出现在两个地方,分别是函数定义处和函数调用处,这两个地方的参数是有区别的。
形参(形式参数)
在函数定义中出现的参数可以看做是一个占位符,它没有数据,只能等到函数被调用时接收传递进来的数据,所以称为形式参数,简称形参。
实参(实际参数)
函数被调用时给出的参数包含了实实在在的数据,会被函数内部的代码使用,所以称为实际参数,简称实参。

形参和实参的功能是传递数据,发生函数调用时,实参的值会传递给形参。

形参和实参的区别和联系

  1. 形参变量只有在函数被调用时才会分配内存,调用结束后,立刻释放内存,所以形参变量只有在函数内部有效,不能在函数外部使用。

  2. 实参可以是常量、变量、表达式、函数等,无论实参是何种类型的数据,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参,所以应该提前用赋值、输入等办法使实参获得确定值。

  3. 实参和形参在数量上、类型上、顺序上必须严格一致,否则会发生“类型不匹配”的错误。当然,如果能够进行自动类型转换,或者进行了强制类型转换,那么实参类型也可以不同于形参类型。

  4. 函数调用中发生的数据传递是单向的,只能把实参的值传递给形参,而不能把形参的值反向地传递给实参;换句话说,一旦完成数据的传递,实参和形参就再也没有瓜葛了,所以,在函数调用过程中,形参的值发生改变并不会影响实参。

#include <stdio.h>

//计算从m加到n的值
int sum(int m, int n) {
    int i;
    for (i = m+1; i <= n; ++i) {
        m += i;
    }
    return m;
}

int main() {
    int a, b, total;
    printf("Input two numbers: ");
    scanf("%d %d", &a, &b);
    total = sum(a, b);
    printf("a=%d, b=%d\n", a, b);
    printf("total=%d\n", total);

    return 0;
}

运行结果:

Input two numbers: 1 100↙
a=1, b=100
total=5050

在这段代码中,函数定义处的 m、n 是形参,函数调用处的 a、b 是实参。通过 scanf() 可以读取用户输入的数据,并赋值给 a、b,在调用 sum() 函数时,这份数据会传递给形参 m、n。

从运行情况看,输入 a 值为 1,即实参 a 的值为 1,把这个值传递给函数 sum() 后,形参 m 的初始值也为 1,在函数执行过程中,形参 m 的值变为 5050。函数运行结束后,输出实参 a 的值仍为 1,可见实参的值不会随形参的变化而变化。

以上调用 sum() 时是将变量作为函数实参,除此以外,你也可以将常量、表达式、函数返回值作为实参,如下所示:

total = sum(10, 98);  //将常量作为实参
total = sum(a+10, b-3);  //将表达式作为实参
total = sum( pow(2,2), abs(-100) );  //将函数返回值作为实参
  1. 形参和实参虽然可以同名,但它们之间是相互独立的,互不影响,因为实参在函数外部有效,而形参在函数内部有效。

更改上面的代码,让实参和形参同名:

#include <stdio.h>

//计算从m加到n的值
int sum(int m, int n) {
    int i;
    for (i = m + 1; i <= n; ++i) {
        m += i;
    }
    return m;
}

int main() {
    int m, n, total;
    printf("Input two numbers: ");
    scanf("%d %d", &m, &n);
    total = sum(m, n);
    printf("m=%d, n=%d\n", m, n);
    printf("total=%d\n", total);

    return 0;
}

运行结果:

Input two numbers: 1 100
m=1, n=100
total=5050

调用 sum() 函数后,函数内部的形参 m 的值已经发生了变化,而函数外部的实参 m 的值依然保持不变,可见它们是相互独立的两个变量,除了传递参数的一瞬间,其它时候是没有瓜葛的。

指针:
因为 var 没有在内存中移动位置,所以表达式 &var 是一个常量指针。然而,C 也允仵使用指针类型来定义变量。指针变量存储的是另一个对象或函数的地址。我们后面会进一步讨论指向数组和函数的指针。首先,看看如何声明指向非数组对象的指针,语法如下:

类型 * [类型限定符列表] 名称 [= 初始化器];

在声明中,星号(*)表示“指向的指针”。标识符“名称”被声明为一个对象,其对象类型为“类型”,也就是“指向‘类型’的指针”。类型限定符为可选择项,可能包含 const、volatile 和 restrict 的任意组合。

下面是一个简单的例子:

int *iPtr;                           // 声明iPtr作为一个指向int的指针

int 类型是 iPtr 指针所指向的对象的类型。为了让指针能够引用到给定的对象,将该对象的地址赋值给该指针。例如,如果 iVar 是一个 int 变量,那么下面的赋值操作会让 iPtr 指向变量 iVar:

iPtr = &iVar;                         // 使得iPtr指向变量iVar

一般形式的声明包含了用逗号分隔开的声明符列表,每个声明符声明了各自的标识符。在指针声明中,星号(*)是声明符的一部分。我们可以在一个声明中同时定义和初始化变量 iVar 和 iPtr,如下所示:

int iVar = 77, *iPtr = &iVar;  // 定义一个int变量,以及一个指向它的指针

这两个声明中的第二个声明,将 iPtr 初始化为变量 iVar 的地址,这使得 iPtr 指向 iVar。图 1 展示了变量 ivar 和 iPtr 在内存中可能的排列方式。这里的地址为示例所需,纯粹是虚构的。如图所示,存储在指针 iPtr 中的值是对象 iVar 的地址。
在这里插入图片描述
在验证与调试时,输出地址常常有助于判断。函数 printf()提供了一种格式化修饰符:%p。下面语句输出变量 iPtr 的地址和内容:

printf("Value of iPtr (i.e. the address of iVar):       %p\n"
      "Address of iPtr:                                 %p\n", iPtr, &iPtr);

无论指针所指对象的类型是什么,在内存中指针空间的大小(例如,表达式 sizeof(iPtr))都是一样的。换句话说,char 指针所占用的空间和指向大型结构的指针所占用的空间一样。在 32 位计算机上,指针通常是 4 个字节长。

按值传递与按址传递:
按值传递:是把实参的值赋值给形参,相当于copy。那么对形参的修改,不会影响实参的值 。
按址传递: 是传值的一种特殊方式,只是他传递的是地址,不是普通的赋值,那么传地址以后,实参和行参都指向同一个对象,因此对形参的修改会影响到实参。

void exchg_address(int *px,int *py){
//此类是针对地址处的数值进行变化,指针关系不动	
	int tmp=*px;
	*px=*py;//地址处的数值变化 
	*py=tmp;
 }
//此类仅仅转换地址,地址处的数值并无变化 
void exchg_value(int px,int py){
int temp;
tmp=px;
px=py;
py=tmp;
}
int main()
{
#if 0
	int a=4,b=6;
	exchg(&a,&b);                           
	printf("a=%d,b=%d。\n",a,b);   //a=6,b=4
	return 0; 
#endif 
	int a=4,b=6;
	exchg(a,b);                               
	printf("a=%d,b=%d。\n",a,b);  //a=4,b=6
	return 0; 
} 

  • 11
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值