函数是一段可以重复使用的代码,用来独立的完成某个功能。它可以根据用户传递的数据实现相应的功能,就像超市里面的自动收银机器,当顾客的商品条码被录入时,自动收银机器就会根据顾客购买的商品数量和单价计算出总价格,但是当没有商品信息录入时,它就不会去计算商品总价。当然函数也可以不去接收客户传输的数据,但接收用户数据的函数需要在定义时就指明参数,不接收用户数据的函数就不需要定义了,根据这一点就可以将函数分为有参函数和无参函数。
有参函数的定义
Datatype functionname(datatype1,datatype2..) { //函数体 }
Datatype表示函数的返回值类型。
Functionname是函数名。
datatype1,datatype2就是参数列表,函数的参数可以只有一个,也可以有多个,当有多个参数时,参数之间用逗号隔开,参数本质上也是一个变量,所以在接收参数时,要确定参数的类型和名称。
例1:
void test(int I,int j)
例1中test()就是一个有参函数,并且两个参数都是int类型,这两个参数可以当作普通变量,直接在函数test()中使用。
无参函数的定义(如果函数不接受用户传递的数据,那么定义时可以不用)。
Datatype functionname();
参数列表里面没有任何变量,这样的函数就是无参函数。
参数的传递(值传递和地址传递)
值传递和地址传递有什么区别呢?
值传递可以理解成单纯的拷贝,把主函数变量的值拷贝一份给子函数,子函数拿着这个变量去做的任何运算都和主函数没关系,假如把小明的空白试卷复印一份给小华,小华拿着这份复印的试卷考了100分,那这100分和小明有没有关系呢?肯定没有的,这和参数传递中的值传递是一个原理,单纯的拷贝,拷贝完后二者再无任何关系。
例1:值传递
int func(int i) { i++; printf(“i = %d ”,i);//i = 11; } int main() { int a = 10; func(a); printf(“a = %d ”,a);//a = 10 }
(值传递内存图)
例1中将主函数的变量a以值传递的方式传递给子函数,子函数中用相同的数据类型变量i接收,此时i和a的值都为10,在子函数中,变量i做一次自加运算后,i的值变为11,但主函数中变量a在不做任何运算的情况下,始终为10。由此可以看出,通过值传递的方式传递的参数,只是单纯的拷贝了主函数变量的值,拷贝完成后,两个变量之间没有任何关联。
地址传递和值传递在本质上就有很大的不同,在C语言的学习中我们明白了一个道理,如果知道一个变量的地址,可以通过地址去访问变量的值,也可以去改变变量的值,在传参的过程中用地址传递的方式,将主函数中变量的地址传给子函数中相同数据类型的指针变量。
例2:
int func(int *i) { (*i)++; printf(“*i = %d ”,*i);//*i = 11; } int main() { int a = 10; func(&a); printf(“a = %d ”,a);//a = 11 }
(地址传递内存图)
可以看出,当使用地址传递的方式传递参数时,子函数中的变量一旦发生改变,主函数中的变量也会随之发生改变,两者像是一根绳子上的蚂蚱。在地址传递里需要注意一点,子函数在接收参数时,需要用相同数据类型的指针来接收主函数传过来的地址,因为指针是存放地址的变量。
函数的返回值
函数的参数可以有多个,但是返回值只能有一个。
例:
int func(int a) { return a;//返回值 }
(返回值内存图)
当子函数中的值返回给主函数后,子函数这一段内存也随即被释放(如下图所示)。
以上函数中的返回值是两个整型变量之和,返回值的类型也就是整型,所以函数的返回值类型就是Int型,返回值类型的设定必须和函数中确定要返回的值的类型一致。