函数
- 什么是函数
在设计一个较大程序是,往往将他们分成若干个程序模块,每一个模块包括一个或多个函数,每一个函数实现一个特定的功能。此时函数分为:主函数和其他函数。
将每一个函数设计好之后,在主函数中运行,实现其功能。
举个例子
输出
***************************
How do you do!
***************************
实现这个程序,如果直接实现很容易,直接输出就行,我们今天用函数的方式输出!
源码:
#include<stdio.h>
int main(){
void print_1(); //声明print_1函数
void print_2(); //声明print_2函数
print_1(); //调用print_1函数
print_2(); //调用print_2函数
print_1(); //调用print_1函数
return 0;
}
void print_1(){
printf("***************************\n");
}
void print_2(){
printf(" How do you do!\n");
}
- 怎样定义函数
定义无参函数:
上面的例子属于无参函数。一般形式为:
函数类型 函数名(){
函数体
}
或
函数名 函数名(void){
函数体
}
注:void表示 函数没有参数
定义有参函数:
int max(int x,int y){
int z;
z=x>y?x:y;
return(z);
}
“z=x>y?x:y”指的是求出z的值,z为x,y中最大的哪一个。
一般形式:
类型名 函数名(形式参数类别){
函数体
}
定义空函数:
类型名 函数名(){}
- 调用函数
函数调用的方式有3中:
函数调用语句 例:上面的pirnt_1()
函数表达式 例:c=2*max(a,b);
函数参数 例:m=max(a,max(b,c));
形式参数和实际参数
形式参数:在定义函数时函数名括号中的变量名称
实际参数:在主函数中调用一个函数时,函数名后面括号中的参数,可以是常量、变量或表达式。
例:输入二个整数,要求输出其中值较大者。要求永安还能输来找到大数。
编写程序:
先写MAX函数
int max(int x,int y){
int z;
z=x>y?x:y;
return(z);
}
再写主函数
#include<stdio.h>
int main(){
int max(int x,int y);
int a,b,c;
printf("输入二个数:\n");
scanf("%d %d",&a,&b);
c=max(a,b);
printf("最大的值为:%d\n",c);
return 0;
}
- 函数的嵌套使用
嵌套函数,就是指在某些情况下,您可能需要将某函数作为另一函数的参数使用,这一函数就是嵌套函数。一个为大家所熟知的例子就是qsort函数会将一个比较器cmp作为参数.又如图1中所示的公式使用了嵌套的 AVERAGE 函数,并将结果与 50 相比较。这个公式的含义是:如果单元格F2到F5的平均值大于50,则求F2到F5的和,否则显示数值0。又如,在一个程序中,主函数调用了sum函数,而在sum函数中又调用了mul函数。在一个函数被调用的过程中又调用另一个函数,这就是函数的嵌套调用。如果是函数本身嵌套调用函数本身,那就是函数递归调用了
- 函数的递归调用
定义:递归调用就是在当前的函数中调用当前的函数并传给相应的参数,这是一个动作,这一动作是层层进行的,直到满足一般情况的的时候,才停止递归调用,开始从最后一个递归调用返回。
调用前:
而从被调用函数返回调用函数之前,系统也应完成3件工作:
(1)保存被调函数的计算结果;
(2)释放被调函数的数据区;
(3)依照被调函数保存的返回地址将控制转移到调用函数。当有多个函数构成嵌套调用时,按照后调用先返回的原则
调用后:
一个函数的运行期间调用另一个函数时,在运行被调用函数之前,系统需要完成3件事情:
(1)将所有的实参、返回地址等信息传递给被调用函数保存;
(2)为被调用函数的局部变量分配存储区;
(3)将控制转移到被调函数的入口。
举个例子:求n!
#include<stdio.h>
int main(){
int fact(int n);
int n;
int y;
printf("输入一个数:\n");
scanf("%d",&n);
y=fact(n);
printf("%d!=%d\n",n,y);
return 0;
}
int fact(int n){
int f;
if(n<0){
printf("n<0,失败");
}
else if(n==0||n==1){
f=1;
}
else f=fact(n-1)*n;
return(f);
}
- 数组作为函数参数
一维数组作为函数的参数
声明数组参数可以采用2种方式:
int strfunc(char *str); //推荐使用
int strfunc(char str[]);
由于数组名作为参数传递给函数时,函数实际接收到的是一个指针,因此第一种声明是更为准确的。在函数内部sizeof(str)的值将会是字符指针的长度,而不是数组的长度。
编译器同样接受第二种声明形式。数组形参无需写明它的元素数目,是因为函数并不为数组参数分配内存空间,形参只是一个指针。因此数组形参可以与任何长度的数组匹配。如果函数需要知道数组的长度,它必须作为一个显式的参数传递给函数。
多维数组作为函数的参数
一维数组作为函数形参,在声明时可以把它写成数组的形式,也可以把它写成指针形式。但对于多维数组,只有第一维可以进行如此选择,这里的关键在于编译器必须知道第2个及后面各维的长度才能对各下标进行求值,因此在原型中必须声明这些维的长度。你可以使用下面2种形式中的任意一种:
void func(int (*mat)[10]);
void func(int mat[][10]);
但写成下面的原型是不正确的:
void func(int **mat);
- 变量
变程序量中使用的范围不同:作用域(Scope),就是变量的有效范围。变量的作用域取决于变量的访问性。
局部变量:函数内部的变量称为局部变量(Local Variable),它的作用域仅限于函数内部, 离开该函数后就是无效的,再使用就会报错。
1.主函数中定义的变量也只能在主函数中使用,不能在其他函数中使用。
2.允许在不同的函数中使用相同的变量名,他们代表不同变量,分配不同的存放单元,互不相干,不会发生混淆。
3.复合语句中定义的变量,只限于使用当前函数中,也是复合语句的局部变量,复合语句:就是用{}包含起来的语句块。
4.形参变量、在函数体内定义的变量都是局部变量。实参给形参传值的过程也就是给局部变量赋值的过程。
全局变量:在所有函数外部定义的变量称为全局变量(Global Variable),它的作用域默认是整个程序,也就是所有的源文件,包括 .c 和 .h 文件。它的作用域是从声明时刻开始,到程序结束。
1.全局变量定义必须在所有函数之外。
2.全局变量可加强函数模块之间的数据联系,但是函数又依赖这些变量,降低函数的独立性。
3.在同一源文件中,允许全局变量和局部变量同名,在局部变量作用域内,同名的全局变量不起作用。
- 内部函数和外部函数
内部函数:
static 类型名 函数名 (参数表)
例如:
static int fun(int a,int b)
表示fun是一个内部函数,不能憋其他文件调用
内部函数又称静态函数
外部函数:
如果在定义函数时,在函数首部的最左端加关键字extern
则此函数时外部函数,可供其他文件调用
extern int fun(int a,int b)
如果在定义函数时省略extern,则默认为外部函数。
#include<stdio.h>
int main()
{
extern void enter_string(char str[]);
extern void delete_string(char str[],char ch);
extern void print_string(char str[]);
char c,str[80];
enter_string(str);
scanf("%c",&c);
delete_string(str,c);
print_string(str);
return 0;
}
void enter_string(char str[80]) //定义外部函数 enter_string
{
gets(str); // 向字符数组输入字符串
}
//file3.c 文件3
void delete_string(char str[],char ch)
{
int i,j;
for(i=j=0;str[i]!='\0';i++)
if(str[i]!=ch)
str[j++]=str[i];
str[j]='\0';
}
void print_string(char str[])
{
printf("%s\n",str);
}
希望有不同见解的,可以提出来呦~