函数的概述与用法

目录

函数概述

库函数

用户自定义函数

有参函数

无参函数

有返回值函数

无返回值函数

主函数

函数的定义

无参函数

有参函数

函数参数

实参和形参

数组作函数参数

main函数

函数的调用

函数调用方式

嵌套调用

递归调用

内部函数和外部函数

内部函数

外部函数

局部变量和全局变量

局部变量


1.函数概述

一个C语言的源程序是由一个或多个函数组成,函数是程序实现模块化编程的基本单元,一般用于完成某一特定的功能。

从函数定义的角度来看,在C语言中可以将函数分为两种:库函数和用户自定义函数。

库函数

库函数由C系统提供,用户无须定义,再调用函数之前也不必在程序中进行类型声明,只需在程序开始部分包括该函数原型的头文件即可在程序中直接调用。例如,在使用scanf函数和printf函数之前,应在程序开始部分包括stdio.h这个头文件。又如,调用字符串操作函数strlen、strcmp等时,也应在程序开始部分包含string.h。

函数得声明与定义

1.如果在主函数前没有函数a,就需要在主函数前加上函数a的声明。

2.如果把a函数的定义置于main函数的文件之前,就可以省略前置声明。

 因为编译器是从上到下进行编译,程序在调用Add函数前没有对其进行声明,编译器不知道什么是Add函数,虽然后面有Add函数,但是编译器这里还是报错,提醒我们Add函数未定义。这时只要在主函数前对Add函数进行声明就可以正常调用Add函数了。

用户自定义函数

就是用户自己编写的用来实现特定功能的函数。

从函数的形式上看,函数分为有参函数和无参函数两种。

有参函数

即在调用函数时,在主调函数和被调函数之间有数据传递。例在上一张图中的mul函数就是有参函数--x,y,在主调函数main和被调函数mul之间传递的数据就是a和b。

无参函数

同有参函数相反,即调用无参函数时,主调函数并不将数据传送给被调用函数。

C语言的函数兼有其它语言中的函数和过程两种功能,从这个角度看,又可把函数分为有返回值函数和无返回值函数两种。

有返回值函数

即调用执行完后将调用者返回一个执行结果,称为函数返回值。如数学函数即属于此类函数。由用户定义的这种要返回函数值的函数,必须在函数定义和函数声明中必须明确返回值的类型。

无返回值函数

即由于完成某项特定的处理任务,执行完成后不向调用者返回函数值。无返回值函数这类函数类似于其它语言中的过程。由于函数无需返回值,用户在定义此类函数时可指定其返回值为“空类型”,空类型的声明符为void

主函数

C程序的执行从main函数开始,在调用完其他函数后流程返回到main函数,在main函数中结束整个程序的运行。

库函数的分类

2.函数的定义

无参函数

一般格式:

类型声明符        函数名()

{        声明部分

           语句        }

“类型声明符”指明了本函数的类型,函数的类型实际上是函数返回值的类型。该类型声明符通常不要求无参函数有返回值,此时函数类型可以写成void。“函数名”是由用户定义的标识符,其后有一个空括号,其中并无参数,但括号必不可少。{}中的内容称为函数体。

有参函数

类型声明符        函数名(形式参数列表)

      声明部分

        语句        }

在“形式参数列表”中给出的参数是形式参数,它们可以是各种类型的变量,同时要对这些变量进行类型声明,各参数类型要用逗号隔开。在进行函数调用时,主调函数将赋予这些实参实际的值

在add函数体中的return语句是把sum的值作为函数的值返回给主调函数。有返回值函数中至少应有一个return语句。

空函数

一般格式:

类型声明符        函数名()

{                        }

空函数什么也不做,没有什么实际作用。那为什么还有存在呢?原因是空函数所处的位置是要放函数的,只是这个函数现在还没有编好,用这个空函数先占一个位置。

3.函数参数

实参和形参

分为实参(例:1)和形参(例x)。

特点:1.形参变量只有在被调用时才分配内存单元,在调用结束时,会释放所分配的内存单元。因此,形参只有在函数内部有效,函数调用结束返回主调函数后则不能使用该形参变量。

2.实参可以是常量、变量、表达式、函数等,但无论它是何种类型的量,在进行函数调用前每个实参必须具有确定的值,一边把这些值传递给形参(如果形参是数组名,则传递的是数组首选地址而不是数组的值,这点后面会提到)

数组作函数参数

1.数组名作函数参数

在编写程序的过程中可以用数组名作函数参数,则种方法实际上是通过数组的首地址传递整个数组。通过下面例子来看如何用数组名来作函数的参数。

注意:

1.形参和实参数组类型应一致。

2.数组名作函数参数时,应该在主调函数和被调函数中分别定义数组。

2.数组元素作函数参数

数组元素只能做函数实参其用法与普通变量完全相同。用数组元素作实参和变量作实参一样,也是单向传递的。

例:从键盘中输入10个数据,计算相邻两个数的和。

语句:add(a[i],a[i+1])就实现了数组元素作实参。

4.main函数

main函数是所有程序运行的入口。

5.函数的调用

函数调用方式

1.函数语句

把函数看作一条语句。只要求函数完成一定的操作,不需要返回值。

2.函数表达式

函数调用出现在一个表达书中。此时调用的函数要有返回值,该表达式需要参与表达式的计算。

例如:x=min(a,b)+max(c,d);

3.函数参数

作为另一个函数的参数调用。例如:x=max(a,min(b,c));

函数min是作为函数max的一个参数调用的,此时要求函数min必须具有返回值,且类型应与函数max的参数类型一致。

嵌套调用

C语言中不允许嵌套的函数定义,因此个函数之间是平行的,不存在上一级函数和下一级函数的问题。但是C语言允许在一个函数的定义中出现对另一个函数的调用,这样就出现了函数的嵌套调用,即在被调用函数中又调用其他函数。这与其它语言的子程序嵌套的情形是类似的。

递归调用

再调用一个函数过程中又出现直接或间接地调用函数本身的情形。例子如上图的gys函数。

递归函数的主要优点是可以把算法写得比使用非递归函数时更清晰、简洁。用户在了解递归后,许多问题还是喜欢用递归来实现,特别是与人工智能有关的问题,更适宜用递归方法来决解。递归的另一个优点是,递归函数不会受到怀疑,较非递归函数而言,某些人更相信也更愿意使用递归函数。

但是:大部分程序的递归形式比非递归形式运行速度要慢一些,这是因为附加的函数调用增加了时间开销,但随CPU、内存还是硬盘较前几年都发生了巨大的变化,所以在许多情况况下,两者运行速度差别不明显。

6.内部函数和外部函数

内部函数

定义:如果在一个源文件中定义的函数只能被本文件中的函数调用,而不能被同一源程序其他文件的函数所调用

一般格式:static         类型说明符       函数名(形参表)            例如:static    int max(int a,int b); 

内部函数也被称为静态函数,但此处静态static的含义已不是指储存方式,而是指对函数调用的调用范围只局限于本文件。

其好处是:不同人编写不同函数时,不用担心自己定义的函数是否会与其他文件中的函数同名,因为同名也没有关系。

外部函数

外部函数在整个源程序中都有效。

一般格式:extern        类型说明符        函数名(参数表)

例如:extern         int           f(int a,int b);

调用外部函数时,需要对其声明。

如在函数定义中没有声明extern或static,则隐含为extern。在一个源文件的函数中调用其他源文件中定义的外部函数时,应使用extern声明被调函数为外部函数。

7.局部变量和全局变量

局部变量

局部变量也称内部变量,是指在函数内部定义的变量。它只在本函数范围内有效。

上面代码中变量a,b,c的有效范围仅限于f1函数内,变量x、y指在主函数内有效。这里f2函数中部分参数和f2中的部分参数相同,不过其名称虽然相同,但是代表不同的对象,之间互不干扰。

复合语句中也可以定义变量,其作用域只在复合语句范围内。这种复合语句也可称为“分程序”或“程序块”。

全局变量

也称外部变量,就是在函数之外定义的变量。其有效作用范围从定义变量的位置开始到该源文件结束。

建议尽可能少使用全局变量:

1.全局变量在程序执行过程中都占用储存单元,并不是在使用时才为其开辟单元。

2.使用全局变量会使函数的移植性降低,因为函数的执行要依赖于其所在的外部变量。如果要将一个函数移到另一个文件中,还有将有关的外部变量及其值一起移过去,如果出现和其他变量重名的问题,这样将会更麻烦。

3.全局变量使用过多,会降低程序的清晰度,因为各个函数执行时都有可能改变全局变量的值。

8.注意事项

1.调用表达式的类型就是函数返回的类型。实参是形参的初始值。函数返回类型不能是函数类型或数组类型,但是可以是指向数组或函数的指针。

2.即使某个形参不被函数用到,也必须给它提供一个实参。

3.没有返回值的return,只能用在void类型的函数中。

4.函数返回值的类型必须与函数返回类型一致,或者能隐式地转换成函数返回类型。

5.函数可以声明多次,但是只能定义一次,声明时可以省略形参,但是一般建议保留,便于理解函数功能。函数声明也叫作函数原型。

6.函数的return语句的作用有两方面:一方面是返回return语句后的值,二是从被调函数返回到主调函数。

7.即使某个形参不被函数用到,也必须给它提供一个实参。

8.main()和main(void)是等价的,只不过前者是隐式地定义空参数列表,而后者是显式地定义了空参数列表。

  • 15
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值