大多数人在进行学习编程时,对于函数调用时函数时的传递的内容是一个头大的问题。本人在学习后有了以下的见解请大家共同学习,若有失误,请指出!
基础知识
形参与实参的传递
1、
先举一个错误的新手容易犯的错误(该程序意用程序实现在交换两个空间的值)
#include <stdio.h>
void exchange(int one,int another);
void exchange(int one,int another) {
int tmp;
tmp = one;
one = another;
num2 = tmp;
}
int main() {
int num1;
int num2;
scanf("%d%d",&num1,&num2);
printf("交换前的值为:%d %d\n",num1,num2);
exchange(num1,mun2);
printf("交换后的值为:%d %d\n",num1,num2);
return 0;
}
结果如下:
对于大多数的编程新手来说,第一次编写类似的代码很容易写成这种情况吧。下面我解释一下,这种方法中,看似交换了num1和num2的值,但实际上。这两个值并没有交换。在主函数中。在堆栈区域申请了两个整形变量空间即num1,和num2的空间。在调用exchange函数时候会现有现场信息(简称:主现。在不涉及多线程中,这里就是eip的值。)保存在堆栈区域,栈顶指针移动向上移动一定的距离。这是为了在此运行主函数时候恢复上次的状态。然后将num2复制一份入栈,another的值对应这个空间的值,栈顶指针向上移动一个整形空间,再将num1复制一份入栈,one的值对应这个空间的值。栈顶指针在向上移动一个整形空间。然后进入到exchange中在堆栈中申请一个整形空间,栈顶指针向上移动一个整形空间。然后进行交换one和another的交换。然后在将栈顶指针恢复到主现以前。然后运行主函数中的代码。上述文字如下图。
接下来我说一种正确代码
#include <stdio.h>
void exchange(int* one,int* another);
void exchange(int* one,int* another) {
int tmp;
tmp = *one;
*one = *another;
*another = tmp;
}
int main() {
int num1;
int num2;
scanf("%d%d",&num1,&num2);
printf("交换前的值为 :%d %d\n",num1,num2);
exchange(&num1,&num2);
printf("交换后的值为 :%d %d\n",num1,num2);
return 0;
}
执行结果为:
上面的代码成功的交换了num1和num2的数值。在主函数中,在堆栈区域申请了两个整形变量空间即num1,和num2的空间。在调用exchange函数时候会现有现场信息(简称:主现。在不涉及多线程中,这里就是eip的值)保存在堆栈区域,栈顶指针移动向上移动一定的距离。这是为了在此运行主函数时候恢复上次的状态。然后将num2地址的值复制一份入栈,another的值对应这个空间的值,栈顶指针向上移动一个整形空间,再将num1地址的值复制一份入栈,one的值对应这个空间的值。栈顶指针在向上移动一个整形空间。然后进入到exchange中在堆栈中申请一个整形空间,栈顶指针向上移动一个整形空间。然后将one指向空间的值赋值给tmp,然后将another所指向空间的值赋值给one所指向空间,最后将tmp的值赋值给another所指向的空间。这就完成了num1和num2的交换。然后在将栈顶指针恢复到主现以前。然后运行主函数中的代码。上述文字如下图
总结提高
在上面的两个例子中,在第一个从错误例子中,我们能发现一个问题,不论我们怎么操作传递到子函数的形参的值,都无法修改主调函数中变量的值。但在第二个例子中,我们可以通过传递主调函数变量的地址值并进行“*”操作就可以改变主调函数中变量的值。这给了我们一个启示:在调用函数中如果不需要修改主调函数中变量的值,传递那个变量的值。如果需要改变主调函数中变量的值,这时候就需要传递的就是该变量的地址的值。但由于传递的值是需要入栈,当传递的变量非常大的时候就会存在危险即栈溢出。所以当需要传递的内容比较大的时候,这时需要传递的仍然是变量的地址,但为了防止被调函数对变量操作。这时候需要加上const!!!
#include <stdio.h>
void exchange(const int* one,const int* another);
void exchange(const int* one,constint* another) {
int tmp;
tmp = *one;
*one = *another;
*another = tmp;
}
int main() {
int num1;
int num2;
scanf("%d%d",&num1,&num2);
exchange(&num1,&num2);
return 0;
}
编译会提示错误如下:
这就对主调函数中变量的值无法操作。