C语言函数

七、函数

所有c程序都是由一个或多个函数组成,一个函数调用另一个函数,前者称为主调函数,后者被称为被调函数

从用户使用角度来看,可分为:标准函数>>>>>即库函数,由C语言提供,用户可以直接调用

用户函数>>>>>人为定义的函数,用以解决用户的专门需求

从函数形式来看,可分为:无参函数>>>>>在调用这类函数时,主调函数并不将数据传送给被调用函数,一般用来执行指定的一组操作

有参函数>>>>>在调用函数时,在主调函数和被调函数之间有数据传递,主调函数可以将数据传递给被调用函数函数使用,被调用函数

中的数据也可以返回供主调函数使用

从函数作用范围来看,可分为:外部函数>>>>>函数在本质上都具有外部性质,除了内部函数外,其余函数都可以被同一程序的其他源文件中的函数调用

内部函数>>>>>内部函数只限于本文件的其他函数调用,而不允许其他文件中的函数调用

1.函数的定义和调用

(1).定义

一般形式:

类型标识符 函数名(形式参数表) //函数的首部

{

说明部分

执行部分

}

类型标识符:说明函数返回值的类型,称为函数值的类型。函数返回值通过return语句返回,系统默认返回值的类型是int型。如果函数只是用来完成某种操作,没

有函数值返回,则为void型,即空类型

函数名:由用户命名的标识符,同一程序中,函数名必须唯一

形式参数表:即形参,形参表可以为空,表示没有参数,也可以由逗号隔开的多个参数组成,括号不能省略(是识别函数的重要标志),同一函数中,形参名必须

唯一,必须说明其类型且只能在本函数内部使用,无形参时,用void表示

函数体:复合语句,由{}括起来,可分为说明部分和执行部分(也可以只有执行部分,或两者都没有即空函数),实现函数功能

说明部分>>>>>变量的定义或所调用函数的声明

执行部分>>>>>由执行语句组成,语句数量不限

函数返回:

1.在返回函数值时,函数值只能通过return语句返回 return 表达式;

2.在不返回函数值时,一种情况是函数体一直执行到函数末尾的“}”,返回到主调函数;另一种情况是使用不含表达式的return语句返回主调函数

(2).调用

函数调用的一般形式:函数名(实际参数表) //实参个数多于一个时,可以用逗号分开

当函数没有形参时,实际参数表为空,调用格式为:函数名()

调用方式:

1.函数语句:把函数调用作为一个语句,即在函数调用的一般形式加上分号即构成函数语句

puts(str);

2.函数表达式:当函数有返回值时,函数可作为运算对象出现在表达式中,函数返回值参与表达式的运算,这种表达式称为函数表达式

z = 3*max(x,y);

2.函数参数(形参、实参及参数值的传递)和函数的值

形参:形式参数

在函数定义中出现的参数可以看做是一个占位符,它没有数据,只能等到函数被调用时接收传递进来的数据,所以称为形式参数,简称形参

实参:实际参数

函数被调用时给出的参数包含了实实在在的数据,会被函数内部的代码使用,所以称为实际参数,简称实参

#include <stdio.h>
​
//计算从m加到n的值
int sum(int m, int n) {
    int i;
    for (i = m+1; i <= n; ++i) {
        m += i;
    }
    return m;
}
​
int main() {
    int a, b, total;
    printf("Input two numbers: ");
    scanf("%d %d", &a, &b);
    total = sum(a, b);
    printf("a=%d, b=%d\n", a, b);
    printf("total=%d\n", total);
​
    return 0;
}

形参实参的区别:

  1. 形参变量只有在函数被调用时才会分配内存,调用结束后,立刻释放内存,所以形参变量只有在函数内部有效,不能在函数外部使用。

  2. 实参可以是常量、变量、表达式、函数等,无论实参是何种类型的数据,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参,所以应该提前用赋值、输入等办法使实参获得确定值。

  3. 实参和形参在数量上、类型上、顺序上必须严格一致,否则会发生“类型不匹配”的错误。当然,如果能够进行自动类型转换,或者进行了强制类型转换,那么实参类型也可以不同于形参类型。

  4. 函数调用中发生的数据传递是单向的,只能把实参的值传递给形参,而不能把形参的值反向地传递给实参;换句话说,一旦完成数据的传递,实参和形参就再也没有瓜葛了,所以,在函数调用过程中,形参的值发生改变并不会影响实参。

  5. 形参、实参可以同名,但是在内存中分配两个不同的存储单元

函数参数的值传递:在调用有参函数时,实参形参之间要进行数据传递,在C语言中,这种传递只能由实参单向传递给形参,这种传递方式称为值传递

形参和实参的功能是传递数据,发生函数调用时,实参的值会传递给形参

3.函数的嵌套调用和递归调用

(1).函数的嵌套调用

C语言的函数定义是相互平行的、独立的,不允许嵌套函数定义,即一个函数内不能包含另一个函数的定义。但是允许在一个函数中对另一个函数进行调用,而另

一个函数中又可以调用第三个函数

原理:执行到main函数中调用a函数的语句时,程序转去执行a函数;在a函数中调用b函数时,转去执行b函数,b函数执行完毕,返回a函数的断点继续执行,a函

数执行完毕返回main函数的断点继续执行

(2).函数的递归调用

一个函数在它的函数体内调用它自身称为递归调用,这种函数称为递归函数,调用可分为直接递归调用和间接递归调用

直接递归调用:函数直接调用它本身

间接递归调用:函数通过其他函数间接调用它自身

使用递归的两个条件:1.要有递归公式。 2.要有终止条件。

用递归实现 1+2+3+…+100 的和

# include <stdio.h>
int Sum(int n);  //函数声明
int main(void)
{
    int n;
    printf("请输入n的值:");
    scanf("%d", &n);
    printf("sum = %d\n", Sum(n));
    return 0;
}
int Sum(int n)
{
    if (n <= 0)
    {
        return -1;
    }
    else if (1 == n)
    {
        return 1;
    }
    else
    {
        return n+Sum(n-1);
    }
}

4.数组作为函数参数

(1).数组元素作为函数实参

数组元素就是下标变量,它与普通变量并无区别。 因此它作为函数实参使用与普通变量是完全相同的,在发生函数调用时,把作为实参的数组元素的值传送给形

参,实现单向的值传送

判别一个整数数组中各元素的值,若大于0 则输出该值,若小于等于0则输出0值

#include <stdio.h>
​
void nzp(int v){
    if(v>0)
        printf("%d ",v);
    else
        printf("%d ",0);
}
​
int main(void){
    int a[5],i;
    printf("input 5 numbers\n");
    for(i=0;i<5;i++){
        scanf("%d",&a[i]);
        nzp(a[i]);
    }
​
    return 0;
}

(2).数组名作为函数实参

数组名作为函数参数时,形参和实参都应使用数组名,并且要求实参和形参数组类型、维数相同。按单向传递方式传递地址,即将实参数组名代表的数组首地址传

递给形参数组名,不是将实参数组的每个元素一一传送给形参各数组的元素

数组a中存放了一个学生5门课程的成绩,求平均成绩

#include <stdio.h>
​
float aver(float a[5]){
    int i;
    float av,s=a[0];
    for(i=1;i<5;i++)
        s=s+a[i];
    av=s/5;
    return av;
}
​
int main(void){
    float sco[5],av;
    int i;
    printf("\ninput 5 scores:\n");
    for(i=0;i<5;i++)
        scanf("%f",&sco[i]);
    av=aver(sco);
    printf("average score is %5.2f",av);
    return 0;
}

(3).多维数组名作为函数实参

与一维数组类似

5.局部变量和全局变量

按照变量的作用域不同,可分为:局部变量和全局变量

(1).局部变量(内部变量)

在函数内部定义的变量只能在本函数内使用,其他函数不能使用>>>>>局部变量

函数的形参也属于局部变量

(注意:

1.在不同的作用域允许有同名变量出现,这些同名变量分别代表不同的对象,分配不同的内存单元,互不干扰

2.局部变量的定义必须放在函数体中全部可执行语句之前

3.主函数中定义的变量只能在主函数内部使用,主函数中也不能使用其他函数中定义的局部变量

4.当作用域发生嵌套时,如果内外层具有同名的局部变量,则在内层起作用的时内层定义的局部变量,外层定义的变量不可见)

int f1(int a){
    int b,c;  //a,b,c仅在函数f1()内有效
    return a+b+c;
}
int main(){
    int m,n;  //m,n仅在函数main()内有效
    return 0;
}

(2).全局变量(外部变量)

在函数外部任意位置上定义的变量,从变量定义的位置开始,到它所在源文件结束为止,作用域中所有函数都能使用相应的全局变量

(注意:

1.不必要时尽量不要使用全局变量,会使函数独立性降低

2.在同一源文件中,允许全局变量和局部变量同名,在局部变量的作用域内,全局变量不起作用)

int a, b;  //全局变量
void func1(){
    //TODO:
}
​
float x,y;  //全局变量
int func2(){
    //TODO:
}
​
int main(){
    //TODO:
    return 0;
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值