自定义函数
自定义函数和一般的函数一样都是有函数名,返回值类型和函数参数。
函数参数
函数的参数有两个,分别是形式参数和实际参数
实际参数(实参)
真是传给函数的值成为实际参数。实参可以是:变量,常量,表达式,函数等。需要注意的是,无论是什么类型的量,在进行函数调用的时候都必须具有确定的值,进而才能将参数传递给函数。
Swap1(a, b);//传值调用
在上述代码中,a和b就是Swap1函数的实际参数。
形式参数(形参)
形式参数指的是函数括号中的变量,用来接收实参。形式参数只有在函数被调用的时候才会被实例化(即分配相应的内存),因此被称为形式参数。形式参数只有在函数中有效,当函数调用完成之后就会被销毁。
void Swap1(int x,int y)
在上述代码中,x和y就是Swap1函数的形式参数。
通过指针对形式变量和实际变量分别取地址可以知道,两种变量的地址是不一样的,都会同时拥有自己的内存空间,即使两个参数的值是一样的。
总结:形参实例化之后相当于实参的一份临时拷贝。
函数调用
介绍完形参和实参之后,再介绍函数调用会方便许多。
函数的调用分为传值调用和传址调用。
传值调用
仅是将实参的值传给形参,因为形参与实参同时占有不同的内存单元,所以改变形参的值并不会改变实参的值。
传址调用
通过在函数外部调用的时候将变量的内存地址(实参)传递给函数形参的一种函数调用方式。再结合"*"
解引用操作符间接访问变量,从而改变变量的值。这种调用方式可以将函数和函数外的变量建立起真正的联系,也就是在函数内部可以直接操作函数外部的变量。
一段简单的代码
void Swap2(int* x, int* y)
{
int temp = 0;
temp=*x;
*x = *y;
*y = temp;
}
void Swap1(int x,int y)
{
int temp = 0;
temp = x;
x = y;
y = x;
}
int main()
{
int a = 10;
int b = 20;
printf("a=%d,b=%d\n", a, b);
Swap1(a, b);//传值调用
printf("a=%d,b=%d\n", a, b);
Swap2(&a,&b);//传址调用
printf("a=%d,b=%d\n", a, b);
return 0;
}
运行结果:
10,20
10,20
20,10
上述代码是通过函数进行交换两个变量的值。
上述代码主要体现出了传值调用和传址调用的区别。
代码中的Swap1函数即是传值调用,即将函数当中将两个形式变量的值进行了调换,但并不会改变函数外部的变量,因此运行结果为10,20;代码中的Swap2函数即是传址调用,即取地址符"&"
将函数外部的变量的地址传给形参,再在函数内部通过解引用操作间接访问变量,进而将两变量的值进行变换。
函数的嵌套调用和链式访问
嵌套调用
即一个函数中可以包含另外一个函数的使用,通过嵌套调用进行有机结合,比较像循环中所讲的嵌套式循环。
链式访问
把一个函数的返回值作为另一个函数的参数
printf("%d", printf("%d", printf("%d", 43)));
运行结果:4321
上述代码是链式访问当中的一个比较有意思的例子。
因为printf函数的返回值是是输出的字符数量,包括数字,字母,标点符号,空格等。最靠内的printf函数接收的值是43,打印,其返回值是2,进而中间的printf函数接收的值是2,其返回值是1,所以最靠外的printf函数接收的值是1,便打印1。所以最终运行结果是:4321.