C语言学习——函数

目录

八、函数

8.1概述

8.2函数定义的一般形式

无参函数

有参函数

空函数

8.3函数参数和函数的值

形式参数和实际参数

函数的返回值

8.4函数的调用

函数调用的一般形式

函数调用的方式

1.函数语句

2.函数表达式

3.函数参数

对被调用函数的声明和函数原型

8.5函数的嵌套调用

8.6函数的递归调用


八、函数

8.1概述

        一个较大的程序一般应分为若干程序模块,每一个模块用来实现一个特定的功能。所有高级语言中都有子程序这个概念,用子程序实现模块的功能。在C语言中,子程序的作用是由函数来完成的。一个C程序可由一个主函数和若干函数来构成的。由主函数调用其他函数,其他函数也可以相互调用。同一个函数可以被一个或者多个函数调用任意多次。

        在程序开发中,常将一些常用的功能模块编写成函数,放在公共函数库供大家选用。所以,我们要善于利用函数,以减少重复编写程序段的工作量。

8.2函数定义的一般形式

无参函数

定义无参函数的一般形式:

类型标识符 函数名 ()

{

声明部分

语句部分

}

有参函数

定义有参函数的一般形式:

类型标识符 函数名 (形式参数表列)

{

声明部分

语句部分

}

例如:

int max(int x, int y)
{
    int z;      //函数体中的声明部分
    z = x>y?x:y;
    return z;
}

如果在定义函数时不指定函数类型,系统会隐含指定函数类型为int型。因此上面定义的max函数左端的int可以省写。

空函数

空函数的定义形式为:

类型说明符 函数名()

{ }

例如:

int dummy(){}

8.3函数参数和函数的值

形式参数和实际参数

在调用函数时,大多数情况下,主函数和调用函数之间有数据传递的关系。这就是前面提到的有参函数。

在定义函数时函数名后面括号中的变量名称为“形式参数”,简称“形参”。

在主函数中调用一个函数时,函数后面括号中的参数(可以是一个表达式)称为“实际参数”,简称“实参”

调用函数时的数据传递

#include
​
int main()
{
    int max(int x, int y);   //对max函数声明
    int a,b,c;
    scanf("%d%d",&a,&b);
    c = max(a,b);
    printf("max is %d\n",c); 
    return 0;
 } 
 
int max(int x, int y)
{
    int z;
    z = x>y?x:y;
    return z;
}

关于形参和实参的说明:

  • 在定义函数中指定的形参,在未出现函数调用时,它们并不占内存中的存储单元。只有在发生函数调用时,函数max中的形参才被分配到内存单元,在调用结束后,形参所占的内存单元也被释放。

  • 实参可以是常量、变量或表达式。例如:max(3,a+b),但是要求他们有确定的值,在调用时将实参的值赋给形参。

  • 在被定义的函数中,必须指定形参的类型。

  • 实参和形参的类型应相同或赋值兼容。

  • 在C语言中,实参向形参的数据传递是“值传递”,单向传递,只由实参传给形参,而不能有形参传回来给实参。在内存中,实参单元与形参单元是不同的单元。

    在调用函数时,给形参分配存储单元,并将实参对应的值传递给形参,调用结束后,形参单元被释放,实参单元仍保留并维持原值。因此,在执行一个被调用函数时,形参的值如果发生改变,并不会改变主调函数的实参的值。

函数的返回值

通常,希望通过函数调用使主调函数能得到一个确定的值,这就是函数的返回值。下面对函数值作一些说明:

(1)函数的返回值是通过函数中的return语句获得的。return语句将被调用函数中的一个确定的值带回主调函数中去。如果需要从被调用函数带回一个函数值(供主函数使用),被调用函数中必须包含一个return语句。如果不需要从被调函数带回函数值可以不要return语句。

return语句后面的括号也可以不要,如“return z”等价于“return (z)”。

return后面的值可以是一个表达式。

(2)函数值的类型函数的返回值属于某一确定的类型,所以,应当在定义函数时指定函数值的类型。

在C语言中,凡不加类型说明的函数,自动按整型处理。

(3)在定义函数时指定的函数类型一般应该和return语句中的表达式类型一致。

如果函数值的类型和return语句中表达式的类型不一致,则以函数类型的为准。对数值型数据,可以自动进行类型转换。即函数类型决定返回值的类型。

返回值类型于函数类型不同。将上面的代码稍作改动(注意:是变量的类型改动)

#include
​
int main()
{
    int max(float x, float y);   //对max函数声明
    float a,b;
    int c;
    scanf("%f%f",&a,&b);
    c = max(a,b);
    printf("max is %d\n",c); 
    return 0;
 } 
 
int max(float x, float y)
{
    float z;  
    z = x>y?x:y;
    return z;
}
//输入 1.5 2.5
//输出:max is 2

解释:函数max定义为整型,而return语句中的z为实型,二者不一致。按上述规定,现将z转换为整型,然后max(x,y)带回一个数值2返回主调函数main。如果将main函数中的c定义为实型,用%f格式输出,也是输出2.000000。

(4)对于不带回值的函数,应当用“void”定义函数为“无类型”(或称“空类型”)。这样,系统就保证不使函数带回任何值,即禁止在调用函数中使用被调函数的返回值。此时,在函数体中不得出现有返回值的return语句。

8.4函数的调用

函数调用的一般形式

函数名(实参表列)

  • 如果是调用无参函数,则:实参表列“可以没有,但括号不能省略。

  • 如果实参表列包含多个实参,则各个参数间用逗号隔开。

  • 实参和形参的个数应相等,类型应匹配。

  • 实参和形参按顺序对应,一一传递数据。

函数调用的方式

按函数在程序中出现的位置来分,可以有以下3种函数调用方式。

1.函数语句

把函数调用作为一个语句。这时不要求函数带回值,只要求函数完成一定的操作。

max();
2.函数表达式

函数出现在一个表达式中,这种表达式称为函数表达式。这时要求函数带回一个确定的值一参加表达式的计算。

c = 2*max(a,b); //max只是表达式的一部分
3.函数参数

函数调用作为一个函数的实参。例如:

//1.
m = max(a,mx(b,c));
//2.
printf("%d",max(a,b));

函数调用作为函数的参数,实质上也是函数表达式形式调用的一种,因为函数参数本来就要求表达式形式。

对被调用函数的声明和函数原型

在一个函数中调用另一个函数(即被调用函数)需要具备的条件如下。

  • 首先调用的函数必须是已经存在的函数(是函数库或者用户自己定义的函数)。

  • 如果使用库函数,还应该在本文件开头用#include命令将调用有关函数时所需用到的信息“包含”到本文件中。

  • 如果使用用户自己定义的函数,而该函数的位置在调用它的函数(即主调函数)的后面(在同一文件中),应该在主调函数中队被调用的函数作声明。

函数原型的一般形式有两种:

  • 函数类型 函数名(参数类型1,参数类型2,··· 参数类型n);

  • 函数类型 函数名(参数类型1 参数名1,参数类型2 参数名2, ··· ,参数类型n 参数名n);

8.5函数的嵌套调用

C语言的函数定义是互相平行、独立的,也就是说,在定义函数时,一个函数内不能包含另一个函数。

C语言不能嵌套定义函数,但可以嵌套调用函数,也就是说,在调用一个函数的过程中,又调用另一个函数。

8.6函数的递归调用

在调用一个函数的过程中又出现直接或间接地调用该函数本身,称为函数的递归调用。C语言的特点之一就是在于允许函数的递归调用。例如:

int f(int x)
{
    int y,z;
    z=f(y);
    return (2*z);
}

递归调用会无终止的自身调用。而程序中是不应该出现这种情况的,而应出现有限次数、有终止的递归调用,这可以用if语句来控制,只有在某一条件成立时才继续执行递归调用;否则就不再继续。

声明:本文章为个人学习笔记,资料整理参考谭浩强《C程序设计(第三版)》如有错误,欢迎大家指正!

你可能感兴趣的:(C语言,c++,c语言)