函数是一个完成特定工作的独立程序模块,包括库函数和自定义函数两种。例如scanf()和printf()等为库函数,由C语言系统提供定义,编程时只要直接调用即可;库函数中没有的函数,用户可以自己来定义,来得到一个明确的计算结果,使得代码变得更简洁明了。
函数定义的一般形式为:大括号{}和小括号()必须存在。
函数类型 函数名(形式参数表) /*函数首部*/
{
函数实现过程 /*函数体*/
}
由函数类型、函数名、形式参数表(简称形参表)组成,位于函数的第一行。函数首部中,函数名是函数整体的称谓,需要一个合法的标识符表示。函数类型指函数结果返回的类型,一般与函数最后一句的return语句中表达的类型一致。形参表中给出函数计算所要用到的相关已知条件,以类似变量定义的形式给出,其格式为:
类型1 形参1,类型2 形参2,...,类型n 形参n
形参表中各个形参之间用逗号分隔,每个形参前面的类型必须分别写明。数量可以是一个,多个,也可以没有形参。
例如: double cylinder(double r,double h)
表明函数类型、函数结果类型是double;函数名是cylinder;形参有两个r和h,都是double型,在cylinder()函数被调用时,这两个形参由主函数给出。
我们常见的主函数框架也符合如上定义。
#include
int main(){ ... return 0; }
- int指主函数返回int类型的结果,所以return后是一个整型。
- main是主函数名。
- 这种写法的形参为void,已经省略了,表明它在调用的时候不能传入任何参数,那么它也就不能获取命令行参数了。int main(void)
函数体是函数的实现过程,由一对大括号内的若干条语句组成,用以计算或特定的工作,并用return返回运算的结果。大括号必须存在。
注意:在函数体中定义的变量,是普通变量,是在这个函数中使用的局部变量,不是形参。
定义一个函数后,就可以在程序中调用这个函数。就像调用标准库函数时,只需要在程序的最前面用#include命令包含相应的头文件;调用自定义函数时,程序中必须先有此函数的定义。
1、函数调用过程:
任何C语言都是从主函数main()开始执行的,若遇到某个函数调用,则主函数被暂停执行,转而执行相应的函数,该函数执行完后再返回函数继续执行主函数。
2、函数调用的形式:
一般形式:函数名(实际参数表)
实际参数(简称实参),可以是常量、变量和表达式。这些值会被按照顺序依次来初始化函数中的参数。
3、参数传递:
举例:自定义求和函数去使用:
#include
void sum(int begin,int end) {
int sum=0;
for(int i=begin;i<=end;i++){
sum+=i;
}
printf("%d到%d的和是%d\n",begin,end,sum);
}
int main(){
int a=0;
int b=0;
scanf("%d %d",&a,&b);
sum(a,b);
sum(1,10);
sum(20,30);
sum(35,45);
return 0;
}
/*
void指不返回任何东西,没有结果被返回。
begin和end是函数的形参。
a和b是实参。(作为参数要传到自定义函数中)
*/
举例:验证形参的值不会影响实参的值:
#include
int max(int a,int b) {
int c=0;
if(a>b) c=a;
else c=b;
return c;
}
int main(){
int a,b,c;
a=5;
b=6;
c=max(10,12);
printf("%d\n",c);
c=max(a,b);//依旧是5和6,不会被max里a、b的值改变
printf("%d\n",c);
c=max(c,23);
printf("%d\n",c);
return 0;
}
4、函数结果返回:
函数结果返回的形式如下:
return 表达式;
- 一般情况下,return语句中的表达式的类型应与函数类型一致;如果不一致,则以函数类型为准。
- return语句的作用有两个:一是结束函数的运行;二是带着运算结果(表达式的值)返回主函数。
- return语句中的表达式反映了函数运算的结果,通过return语句将改结果返回给主函数。
- return语句只能返回一个值,如果函数产生了多个运算结果,将无法通过return返回。
- 可以有多个的return语句。
- 返回值可以赋值给变量,可以再传递给函数,甚至可以丢掉。
没有返回值的函数形式:可以没有return,不能使用带值的return,调用的时候不能做返回值的赋值。
void 函数名(参数表)
5、函数原型声明:
C语言要求函数先定义后调用,就像变量先定义后使用一样。如果自定义函数被放在主函数的后面,则需要在函数调用前,加上函数原型声明(或函数声明)。即与函数定义中的第一行(函数首部)相同,不同的是函数声明是一条语句,需要以分号结束,函数定义时不是语句,不能跟分号。
在先定义后调用的前提条件下,函数声明可以写在主函数内,也可以写在头文件那里。
函数声明的一般格式为:函数类型 函数名(参数表);
#include
int main(){ int a=0; int b=0; scanf("%d %d",&a,&b); void sum(int begin,int end); sum(a,b); sum(1,10); sum(20,30); sum(35,45); return 0; } void sum(int begin,int end) { int sum=0; for(int i=begin;i<=end;i++){ sum+=i; } printf("%d到%d的和是%d\n",begin,end,sum); } 如果在函数调用前,不定义,不声明,程序编译就会出错。
使用自定义函数程序有以下几个优点:
1、程序结构清晰,逻辑关系明确,程序可读性强;
2、解决相同或相似问题时不用重复编写代码,可通过调用函数来解决,减少代码量。
3、利用函数实现模块化编程,各模块功能相对独立,可以降低调试难度。
可以自定义函数判断这个数是否是完全平方数,本例中出现了两个return语句,执行时根据条件选择其中的一个,它们的作用相同,即结束函数与奴性,并会送结果。return之后的语句将不会被执行。
例1、判断n是否是完全平方数:
#include
int IsSquare(int n) {
//若n是完全平方数,则存在正整数m,使得m^2=n ,也有n=1+3+5+...+(2m-1)
for(int i=1;n>0;i+=2){
n=n-i;
}//25=1+3+5+7+9+11
if(n==0) return 1;//是完全平方数
else return 0;//不是完全平方数
}
int main(){
int n=0;
scanf("%d",&n);
if(IsSquare(n)==1) printf("是");
else printf("不是") ;
return 0;
}
例2、素数求和 其中判断是否是素数的函数
int IsPrime(int i) {
int ret=1;//是素数
for(int k=2;k<=i;k++) {
if(i%k==0){
ret=0;//不是素数
break;
}
}
return ret;
}
关于函数的一些细节:
- 不允许函数嵌套定义。
- 调用函数时的圆括号里的的逗号是标点符号,不是逗号运算符。f(a,b)是标点符号;f((a,b))是逗号运算符,要先做括号里的运算。
- 返回语句return (i)没错,返回i的值,但是会让人误以为是个函数,没有意义因此不建议这样写。