目录:
1.自定义详解
2.疑问解答
3.函数的参数
4.有关return的提醒
5.数组作函数的参数
6.函数调用的方式
传值调用
传址调用
1、自定义详解
*提示:先看第12,19篇
例:写一个程序交换两个变量的值
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
void swap(int x, int y)
{
int z = 0;
z = x;
x = y;
y = z;
}
int main()
{
int a = 10;
int b = 20;
swap(a, b);
printf("%d %d",a, b);
}
函数名前些void,表示无返回类型,即不需要写return xxx;
输出结果显示:a,b并没有交换
打开调试模式,键入F11,打开监视
程序执行一遍后:
x和y的值虽然被交换,但是a和b的值并没有交换
原因:由&a &b &x &y知道:a和x的地址不同,b和y的地址不同
另一种解释(见第3点):swap在被调用时,实参(a,b)传给形参(x,y),形参是实参的临时拷贝,所以改变形参,不改变实参
解决方案:回想第19篇用地址(*pa)来控制变量(a),让a和x,b和y建立联系
-->把a,b的地址交给自定义函数的指针
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
void swap(int* pa, int* pb)
{
int z = 0;
z = *pa;
*pa = *pb;
*pb = z;//*pa等效于main函数中的a,*pb等效于main函数中的b
}
int main()
{
int a = 10;
int b = 20;
swap(&a, &b);
printf("%d %d",a, b);
}
&a和&*pa,&b和&*pb一样
2.疑问解答:
Q:为什么第12篇创建函数时为什么没有使用指针?
A:第12篇讲的是求两个数的和,并没有改变输入的x和y,因此不用指针。所以自定义函数要使用指针的前提是改变变量
3.函数的参数
实际参数(实参):
真实传给函数的参数,叫实参。实参可以是:常量、变量、表达式、函数等。无论实参是何种类
型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。
形式参数(形参):
形式参数是指函数名后括号中的变量,因为形式参数只有在函数被调用的过程中才实例化(分配
内存单元),所以叫形式参数。形式参数当函数调用完成之后就自动销毁了。因此形式参数只在
函数中有效(生命周期类似局部变量)。
如:swap(a,b);的a和b是实际参数,swap(2,3)的2和3是实际参数,void swap(m,n)的m和n是形式参数
注意:1.形参的个数可以为0个或1个或2个或多个
2.形参的个数要和实参匹配上
3.形参和实参的名字可以相同
4.有关return的提醒
• return后边可以是一个数值,也可以是一个表达式,如果是表达式则先执行表达式,再返回表达式
的结果。
如:
int main()
{
return 0;
}
main函数中返回0表示正常返回,非0表示异常返回
• return后边也可以什么都没有,直接写return; 这种写法适合函数返回类型是void的情况。
• return返回的值和函数返回类型不一致,系统会自动将返回的值隐式转换(自动进行类型转换)为函数的返回类型。
• return语句执行后,函数就彻底返回,后边的代码不再执行。
• 如果函数中存在if等分支的语句,则要保证每种情况下都有return返回,否则会出现编译错误。
int test(int a)
{
if (a<0)
return 1;
}
int main()
{
int b=test(2);
}
编译器会报警告: 不是所有的控件路径都返回值
注意:1.函数的返回类型如果不写,VS会默认返回int类型
2.如果一个函数有明确的返回类型,但函数内部没有写return 返回值,则返回值不确定
5.数组做函数参数
如:
void set_arr(int arr[], int sz)
{
int i = 0;
for(i=0; i<sz; i++)
arr[i] = -1;
{
不写成 *arr[]的原因:数组传参传的是数组的地址,在形参部分访问数组时,操作的是主调函数(即main函数)中的数组
注意:数组在传参的时候,对于一维数组,在形参部分不会新建数组(形参操作的数组和实参的数组是同一个数组),所以arr[]可以省略数组的大小,对于二维数组,行可以省略,但是列不能省略
6.函数的调用方式
01传值调用
函数的形参和实参分别占有不同内存块,对形参的修改不会影响实参。
void swap(int x, int y)
{
int z = 0;
z = x;
x = y;
y = z;
}
02传址调用
传址调用是把函数外部创建变量的内存地址传递给函数参数的一种调用函数的方式,这种传参方式可以让函数和函数外边的变量建立起正真的联系,也就是函数内部可以直接操作函数外部的变量
void swap(int* pa, int* pb)
{
int z = 0;
z = *pa;
*pa = *pb;
*pb = z;
}