C语言中的函数
在C语言里,函数不一定要有参数、也不一定要计算数值。
C程序由一个main和任意个函数(可有可无)组成。C语言必须要有一个main函数,而且只能有一个main函数,这个函数叫主函数,它是第一个运行的函数。一般来说,主函数应放在最后,其他被调用函数放在主函数前面。这样的话,其他被调用函数可以不予先声明。如果其他被调用函数放在了主函数后面,则在主函数之前一定要事先对被调用函数加以声明。
函数的定义
函数的定义是指对函数功能的确立,包括指定函数名、函数值类型、形参及其类型、函数体等,它是一个完整的、独立的函数单位
一个函数只能被定义一次。但可以声明多次。
其定义形式很简单:
函数返回类型 函数名(形式参数列表)
{ //{}括起来的执行部分,称为函数体。
声明部分;
语句部分;
}
例如 int main()
{
}
在形参列表里,没有数组(a[n]),
只能定义 函数类型 函数名(参数类型 a[] , int n){} 这样来定义一个长度为n的数组a[n]。
但是这种定义里,n和数组a的长度之间没有之间联系。C99以后可以这样定义:
例如:int sum_array(int n, int a[n]){} 但是(int a[n], int n)是非法。
这样写也行int sum_array(int n, int a[*]),或者int sum_array(int , int a[*])
如果要定义一个多维数组,想省略参数的话,声明参数时只能省略第一维的长度。例如,如果修改sum_array函使得a是一个二维数组,我们可以不指出行的数量,但是必须指定列的数量。
例如:int sum_two_dimensional(int a[][LEN], int n){}。
还可以使用static关键字:
int sum_array(int a[static 3] , 这样表明数组a的长度至少可以保证是3:但是static只能用在第一维。
函数的声明
函数的声明的作用是把函数的名字、函数类型及形参的类型、个数和顺序通知编译系统以便在调用该函数时编译系统能正确识别函数并检查调用是否合法。
(隐式声明:C语言中有几种声明的类型名可以省略。例如:函数名如果不显式地声明返回值的类型,那么它默认返回整型;隐式声明不是好习惯)。
简单来说,就是自定义函数要写在main()函数的前面,如果函数定义在了主函数的后面,就需要在主函数前进行 函数声明。
函数声明:
返回类型 函数名 (形参列表); //注意这里一定有分号。因为它只是一条语句。
像这种里面有参数列表的函数声明,称为函数原型,原型为如何调用函数提供了完整的描述。
(其实函数声明不需要说明函数形参的名字,只需要显示它们的类型即可,但是不推荐省略名字。)
例如:double average (double, double);
如果在main函数里遇到了函数调用,就会去找函数,但是,只能在main函数的上面去寻找,如果此时函数定义在了main函数的下面,那么就无法找到函数,从而报错。对于这种情况,有两种解决办法:
1.自定义的函数放在在main函数之前
2.在main函数之前先进行函数声明,然后在main函数之后再进行函数定义。
函数所涉及的变量:
形参:定义一个函数时,有无形参都可以 ,但如果有多个形参,每一个形参都必须分开定义参数类型,哪怕形参的类型一致也必须分开定义。
函数的形式参数本质上是变量,其初始值是在调用函数的时候才提供的,只在该函数内有作用。
实参:主函数传递过来的参数是实际参数,在数量方面和形参要一一对应,但是实参不一定是变量,任何正确类型的表达式都可以。是通过值传递的。
全局变量:在所有的函数(包括主函数)外,定义的变量是全局变量。全局变量i存储在数据段,所以main函数和print函数都是可见的。全局变量不会因为某个函数执行结束而消失,在整个进程的执行过程中始终有效。如果局部变量与全局变量重名,就采取就近原则,即实际获取和修改的值是局部变量的值。
主函数与其他函数之间的关系
在程序编译时是以源程序文件为单位而不是以函数为单位进行编译的。
函数间的调用关系是:由主函数调用其他函数,其他函数也可以相互调用,同一个函数可以被一个或者多个函数任意调用任意次。C语言的执行从main函数开始,如果在main函数中调用其他函数那么在调用后会返回到main函数中,在main函数中结束整个程序的运行。
所有的函数都是平行的,即在定义函数时是分别进行的,并且是互相独立的。一个函数并不属于另一个函数,函数不可以嵌套定义。函数间可以互相调用,但不可以调用主函数,主函数由系统调用。
函数调用
函数调用由函数名和跟随其后的实际参数列表组成,其中实际参数列表用圆括号括起来。
1.不保存的调用:average(x,y);,不会保存它。
2.没有返回值的函数调用,需要自成一个语句→void print_count(int n){},调用:print_count(i);
3.调用不带实际参数的函数时,只需要写出函数名并且在后面加上一对圆括号。即使没有实参也必须带有圆括号。→void print_count(void){},调用:print_count();
4.函数返回规则:函数不能返回数组。若省略函数返回类型,c99会默认返回类型为int。而且函数返回类型可以不和函数名放在同一行,可以放在上面一行。
终止函数
在main()函数里,exit(0);和return 0;是一样的意思,只不过exit函数在<stdlib.h>里。
如果return语句返回的类型和函数返回类型要求的类型不一致,会自动将return返回类型转变为函数所要求的类型。其实,如果没有表达式,那么return 语句是可以出现在void 函数里的。
不一定要在main()函数里终止,可以在其他函数里使用exit()函数。
例:
计算平均值
#include <stdio.h>
double average(double a, double b)
{
return (a + b )/2;
}
/*
double是函数返回类型,a和b是函数的形式参数。
average(5.1,8.9)和average(x/2,y/2)都是合法的函数调用
*/
int main()
{
double x,y,z;//干嘛用???
printf("Enter three numbers: ");
scanf("%lf%lf%lf",&x,&y,&z);
printf("average of %g and %g: %g\n",x,y,average(x,y));
printf("average of %g and %g: %g\n",x,z,average(x,z));
printf("average of %g and %g: %g\n",y,z,average(y,z));
return 0;
}
/*
这里是把函数调用放在输出语句里。
以变量x和变量y作为实际参数调用average函数。
average函数执行自己的return语句,返回a和b的平均值。
printf函数显示出函数average的返回值。
注意:在上面的程序里,并没有保存average函数的返回值。
程序显示值以后就把average函数丢弃。
如果需要在稍后的程序中用到返回值,可以把返回值存储在变量avg中
avg = average(x,y)
*/
#include<stdio.h>
//函数调用
int printstar(int i)//函数声明,声明函数printstar,i为形式参数
{
printf("*****************\n");
printf("printstar %d\n",i);
return i+3;
}
void print_message()//可以调用printstar
{
printf("how do you do \n");
printstar(3);//函数调用
}
int main()
{
int a = 10;
a = printstar(a);
print_message();
printstar(a);
return 0;
}
运行结果:
*****************
printstar 10
how do you do
*****************
printstar 3
*****************
printstar 13
??????不理解。
判断素数
/*
判断素数
素数:除了1和它本身没有其它的除数
*/
#include <stdbool.h>
#include <stdio.h>
//判断素数,返回true则认为是素数,返回是false则认为不是素数
bool is_prime(int n)
{
int divisor;//divisor:除数
if (n <= 1)
{
return false;
}
for (divisor = 2; divisor * divisor <= n ; divisor++)
{
if (n % divisor == 0)
{
return false;
}
}
return true;
}
int main()
{
int n;
printf("Enter a number: ");
scanf("%d",&n);
if(is_prime(n))
{
printf("Prime \n");
}
else
{
printf("Not Prime \n");
}
return 0;
}
快速排序: