函数
定义:
函数就是用来完成一定功能的一段代码(程序)模块。
在设计较大的程序时,一般将其分为若干个程序模块,每个模块用来实现一定的功能。
函数优势:
我们可以通过函数提供功能给别人使用,当然我们也可以使用别人提供的函数,减少代码量。
借助函数可以减少重复性的代码。
实现结构化(模块化)程序设计思想:
将大型的任务功能划分为相互独立的小型的任务模块来设计。
一般形式:
返回类型 函数名(形参列表) ——函数头 | 函数首部
{
函数体语句; ——整个{}包裹的内容包括返回值都属于函数体
}
函数首部:
返回类型:函数返回值的类型
函数名:函数的名称,遵循标识符命名(使用英文字母,数字,符号,下划线,不能以数字开头,建议小写+下划线命名法)
形参列表:用于接收主调函数传递的数据,如果有多个用“ ,”分隔,且每一个形参都需要指定类型。
注意:
● 函数类型标识符,变量类型说明符相同,它表示返回的函数值的类型。
● 在C语言中还可以定义无类型(即void类型)的函数,这种函数不返回函数值,只是完成某种功能。
● 如果省略函数的类型标识符,则默认为是int型。
● 函数中返回语句的形式为 return(表达式);或 return 表达式;其作用是将表达式的值作为函数值返回给调用函数。其中表达式的类型应与函数类型一致。
● 如果形参表中有多个形参,即使它们的类型是相同的,在形参表中也只能逐个进行说明。
double sab(double a,double b)
{ … }
● 一个完整C程序中的所有函数可以放在一个文件中,也可以放在 多个文件中。
说明:
1.在C语言中,函数(function)是构成程序的基本模块。
一个C程序由一个或多个函数组成,有且仅有一个主函数,即main()函数。
2.每个函数完成一个相对独立的且功能明确的任务。由主函数调用其他函数,其他函数也可以互相调用。同一个函数可以被一个或多个函数调用任意多次。
函数分类
从函数实现看:
标准库函数:C语言标准库实现并提供使用的函数,比如常见的有:printf(),scanf()
用户自己定义的函数:需要程序员自行实现,开发中大部分都是这样的函数
从函数形式的角度:
无参函数:函数调用时,无需传参,可配可不配返回值。
有参函数:函数调用时,需要参数传递数据,经常需要配套返回值使用。
相关概念(说明):
主调函数:主动去调用其他函数的函数。(main只能作为主调函数)
被调函数:被调用的函数。
注意:很多时候,一个函数既可以是主调函数,也可以是被调函数,这种情况一般出自自定义数。
案例:
1// 此时main是主调函数,需要注意的是,main只能作为主调函数
2 int main()
3 {
4 // 此时printf()是被调函数
5 printf("hello world!");
6
7 return 0;
8 }
形式参数和实际参数
形参(形式参数):函数定义时指定的参数,形参是用来接收数据的,函数定义时,系统不会为形参申请内存,只有当函数调用时,系统才会为形参申请内存,用于存储实际参数,并且当函数返回,系统会自动回收为形参申请的内存资源。(本质上所有函数都有return,只不过当我们的函数返回类型是void的时候,return关键字被省略了)
实参(实际参数):
函数调用时主调函数传递的数据参数(常量、变量、表达式.,只要有确定的值),实参是传递的数据(副本)。
在C语言中,参数传递遵循单向值传递(只能实参 -->形参),实参只是将自身的值传递给形参,而不是实参本身。形参的值的改变不会影响实参。
实参与形参在内存中占据不同的内存空间,尽管可能实参和形参名称是一样的。
函数的返回值
1.若不需要返回值,函数中可以没有return语句。
2.一个函数中可以有多个return语句,但任一时刻只有一个return语句被执行。
3.被调函数返回给主调函数的结果数据(可以是变量、常量、表达式,只要是有确定值即可。)
4.返回值类型一般情况下需要和函数中return语句返回的数据类型保持一致,如果不一致,以函数定义时指定的返回类型为标准。也就是返回值类型和实际返回值可以存在自动类型转换或者强制类型转换的关系。
eg:
1/*
2 理解:返回值和返回值类型不一致时,转换问题
3 */
4#include <stdio.h>
5
6/**
7 * 求最大值
8 * @param x,y都是形式参数,形式参数本身没有意义,需要赋值实际参数
9 */
10 double max(int x,int y)
11{
12 return (x > y ? x : y);
13}
14
15int main()
16{
17 int a,b,c;
18
19 printf("请输入两个整数:\n");
20
21 scanf("%d,%d",&a,&b);
22
23 c = (int)max(a,b);// 这里的a,b就是实际参数
24
25 printf("%d,%d中的最大数是:%d\n",a,b,c);
26
27 return 0;
28
29}
30
函数的调用
调用方式:
1.函数语句:test();
2.表达式语句:4+max(2,4);
3.函数参数:printf("%d",max(2,4));
在一个函数中调用另一个函数须具备以下条件
①被调用的函数必须是已经定义的函数;
②若使用库函数,应在本文件开头用#include包含:
③若使用用户定义的函数,而用户函数又在主调函数的后面,则应在主调函数中对被调用的函数进行声明。声明的作用是把函数名、函数参数的个数和类型等信息通知编译系统,以便在遇到函数时,编译系统能正确识别函数,并检查函数调用的合法性。
函数声明
函数调用时,往往要遵循先定义后调用 ,但如果我们对函数的调用操作出现在函数的定义之前,则需要对函数进行声明。
函数声明的作用:
是把函数名、函数参数的个数和返回类型等信息通知给编译系统,以便于在遇到函数时,编译系统能正确识别函数,并检查函数调用的合法性。
eg:
错误方式:
1// 函数调用错误演示 2int main() 3{ 4 int c = add(12,13); // 此时会报编译错误,因为函数没有经过声明,所以编译系统无法正确识别函数5 printf("%d\n",c); 6} 7int add(int x,int y) 8{ 9 return x + y; 10}
正确方式:
1// 函数调用正确写法 2// 函数声明和实现放在一起 3int add(int x,int y) 4{ 5 return x + y; 6} 7int main() 8{ 9 int c = add(12,13); // 此时会报编译错误,因为函数没有经过声明,所以编译系统无法正确识别函数10 printf("%d\n",c); 11}
1// 函数调用正确写法 2 3// 在函数调用之前,声明函数 4int add(int x,int y); 5 6int main() 7{ 8 int c = add(12,13); 9 printf("%d\n",c); 10} 11int add(int x,int y) 12{ 13 return x + y; 14}
声明的方式:
函数首部后加上分号;
void fun(int a);
函数首部后加上分号,可省略形参名,但不能省略参数类型。
void fun(int);
函数的嵌套调用
1.函数不允许嵌套定义,但允许嵌套调用。
2.嵌套调用:在被调函数内又去主动去调用其他函数,这样的函数调用方式,称之为嵌套调用;
eg:
1/**
2 * 需求:输入四个整数,找出其中最大的数,用函数嵌套来处理,要求每次只能两个数比较
3 */
4#include <stdio.h>
5
6// 函数声明
7int max_2(int,int);
8int max_4(int,int,int,int);
9
10// 主函数
11int main()
12{
13 int a=12,b=44,c=33,d=16,result;
14
15 result = max_4(12,44,33,16);
16
17 printf("%d,%d,%d,%d中的最大数是%d\n",a,b,c,d,result);
18
19 return 0;
20}
21
22// 求2个数中的最大数
23int max_2(int a,int b)
24{
25 return a > b ? a : b;
26}
27
28
29// 求4个数中的最大数
30int max_4(int a,int b,int c,int d)
31{
32 int max;// 存储比较的最大数
33 max = max_2(a,b);// 第一次比较:a,b中最大数
34 max = max_2(max,c);// 第二次比较:a,b,c中最大数
35 max = max_2(max,d);// 第三次比较:a,b,c,d中最大数36
37 return max;
38}
39