如果库函数能干所有的事情,那还要程序员干什么?
所有更加重要的是自定义函数。
自定义函数和库函数一样,有函数名,返回值类型和函数参数。
但是不一样的是这些都是我们自己来设计。
这给程序员一个很大的发挥空间。
函数的组成
ret_type fun_name(para1, * )
//函数的返回类型 函数名(传入参数)
{
statement;//语句项
}
ret_type 返回类型
fun_name 函数名
para1 函数参数
我们举一个例子:
写一个函数可以找出两个整数中的最大值。
#include <stdio.h>
//get_max函数的设计
int get_max(int x, int y)
{
return (x > y) ? (x) : (y);
}
int main()
{
int num1 = 10;
int num2 = 20;
int max = get_max(num1, num2);
printf("max = %d\n", max);
return 0;
}
我们来看一个例子
//函数返回类型的地方写出:void,表示这个函数不返回任何值,也不需要返回
//写出问题了!
void Swap(int x, int y)
{
int z = 0;
z = x;
x = y;
y = z;
}
int main()
{
int a = 10;
int b = 20;
//写一个函数 - 交换2个整型变量的值
printf("交换前:a=%d b=%d\n", a, b);
Swap(a, b);
printf("交换后:a=%d b=%d\n", a, b);
return 0;
}
为什么没有交换?因为只有函数里的参数交换了,实际上主函数的两个值并没有受影响
该怎么办
//swap1在被调用的时候,实参传给形参,其实形参是实参的一份临时拷贝
//改变形参,不能改变实参
void Swap1(int x, int y)
{
int z = 0;
z = x;
x = y;
y = z;
}
void Swap2(int* pa, int* pb)//
{
int z = 0;
z = *pa;
*pa = *pb;
*pb = z;
}
int main()
{
int a = 10;
int b = 20;
//写一个函数 - 交换2个整型变量的值
Swap1(a, b);//传值调用
printf("交换前:a=%d b=%d\n", a, b);
Swap2(&a, &b);//传址调用
printf("交换后:a=%d b=%d\n", a, b);
return 0;
}
为什么呢,我们来看函数参数的具体介绍
函数的参数
实际参数(实参)
真实传给函数的参数,叫实参。
实参可以是:常量、变量、表达式、函数等。
无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形 参。
形式参数(形参)
形式参数是指函数名后括号中的变量,因为形式参数只有在函数被调用的过程中才实例化(分配内 存单 元),所以叫形式参数。形式参数当函数调用完成之后就自动销毁了。因此形式参数只在函数中有 效。
上面 Swap1 和 Swap2 函数中的参数 x,y,px,py 都是形式参数。
在main函数中传给 Swap1 的 num1 , num2 和传 给 Swap2 函数的 &num1 , &num2 是实际参数。
这里我们对函数的实参和形参进行分析:
这里可以看到 Swap1 函数在调用的时候, x , y 拥有自己的空间,同时拥有了和实参一模一样的内容。
所以我们可以简单的认为:形参实例化之后其实相当于实参的一份临时拷贝。
传值调用
函数的形参和实参分别占有不同内存块,对形参的修改不会影响实参。
传址调用
- 传址调用是把函数外部创建变量的内存地址传递给函数参数的一种调用函数的方式。
- 这种传参方式可以让函数和函数外边的变量建立起真正的联系,也就是函数内部可以直接操 作函数外部的变量。