什么是函数?

函数(function)是完成特定任务的独立程序代码单元。语法规则定义了函数的结构和使用方式。虽然 C 中的函数和其他语言中的函数、方法、子程序、过程作用相同,但是细节上略有不同。
一些函数执行某些动作,如 printf() 把数据打印到屏幕上,一些函数找出一个值供程序使用,如 strlen() 把指定字符串的长度返回给程序。一般而言,函数可以同时具备以上两种功能。

为什么用函数?

首先,使用函数可以省去编写重复代码的苦差。如果程序要多次完成某项任务,那么只需编写一个合适的函数,就可以在需要时使用这个函数,或者在不同的程序中使用该函数,就像许多程序中使用 putchar() 一样。其次,即使程序只完成某项任务一次,也值得使用函数。因为函数让程序更加模块化,从而提高了程序代码的可读性,更方便后期修改、完善。

例如,假设要编写一个程序完成以下任务:读入一系列数字、分类这些数字、找出这些数字的平均值、打印一份柱状图。可以使用下面的程序:

#include <stdio.h>
#define SIZE 50
int main(void)
{float list[SIZE]; readlist(list, SIZE); sort(list, SIZE); average(list, SIZE); bargraph(list, SIZE); return 0;
}

当然,还要编写 4 个函数 readlist()、sort()、average() 和 bargraph() 的实现细节。描述性的函数名能清楚地表达函数的用途和组织结构。然后,单独设计和测试每个函数,直到函数都能正常完成任务。如果这些函数够通用,还可以用于其他程序。

许多程序员喜欢把函数看作是根据传入信息(输入)及其生成的值或响应的动作(输出)来定义的“黑盒”。如果不是自己编写函数,根本不用关心黑盒的内部行为。例如,使用 printf() 时,只需知道给该函数传入格式字符串或一些参数以及 printf() 生成的输出,无需了解 printf() 的内部代码。以这种方式看待函数有助于把注意力集中在程序的整体设计,而不是函数的实现细节上。因此,在动手编写代码之前,仔细考虑一下函数应该完成什么任务,以及函数和程序整体的关系。

如何了解函数?

首先要知道如何正确地定义函数、如何调用函数和如何建立函数间的通信。

#include <stdio.h>
#define NAME "GIGATHINK, INC."
#define ADDRESS "101 Megabuck Plaza"
#define PLACE "Megapolis, CA 94904"
#define WIDTH 40
void starbar(void); /* 函数原型 */
int main(void)
{starbar(); printf("%s\n", NAME); printf("%s\n", ADDRESS); printf("%s\n", PLACE); starbar(); /* 使用函数 */ return 0;
}
void starbar(void) /* 定义函数 */
{int count; for (count = 1; count <= WIDTH; count++) putchar('*'); putchar('\n');
}

该程序的输出如下:


GIGATHINK, INC.
101 Megabuck Plaza
Megapolis, CA 94904


该程序要注意以下几点。程序在 3 处使用了 starbar 标识符:函数原型(function prototype)告诉编译器函数 starbar() 的类型,函数调用(function call)表明在此处执行函数,函数定义(function definition)明确地指定了函数要做什么。

名词解释

1. 函数类型

函数和变量一样,有多种类型。任何程序在使用函数之前都要声明该函数的类型。
例如上面的程序中,函数原型部分 void starbar(void); 其中第一个 void 是函数类型,void 类型表明 starbar() 函数无返回值类型。
PS:如果不声明返回值类型,C 语言默认是返回 int 类型。

2. 函数原型和函数定义

函数原型,也叫函数声明。
例如上面的程序中,void starbar(void); 后面带分号,分号表明这是在声明函数,不是定义函数。也就是说,这行声明了程序将使用一个名为 starbar()、没有返回值、没有参数的函数,并告诉编译器在别处查找该函数的定义。
一般而言,函数原型指明了函数的返回值类型和函数接受的参数类型。这些信息称为该函数的签名(signature)。对于 starbar() 函数而言,其签名是该函数没有返回值,没有参数。

vodi starbar(void) {} 后面带 {} 告诉编译器这是函数定义,而不是调用函数或声明函数原型。

starbar() 函数中的变量 count 是局部变量(local variable),意思是该变量只属于 starbar() 函数。可以在程序中的其他地方(包括main()中)使用 count,这不会引起名称冲突,它们是同名的不同变量。

如果把 starbar() 看作是一个黑盒,那么它的行为是打印一行星号。不用给该函数提供任何输入,因为调用它不需要其他信息。而且,它没有返回值,所以也不给 main() 提供(或返回)任何信息。简而言之,starbar() 不需要与主调函数通信。
接下来我们了解下函数间通信。

函数参数

函数参数是做什么的?

函数间的通信主要是通过函数参数来实现的。
通过函数参数,主调函数可以向被调参数传递一些信息。并且,在我们学习了指针和数组的知识之后,被调函数还可以通过函数参数传递一些信息给主调函数。
PS:被调函数传递信息给主调函数的方法除了函数参数之外,还可以通过返回值。不过返回值的一个缺点是只能返回一个值。

下面我们就来学习一下函数参数的知识。

定义带形式参数的函数

例如,有一个如下所示的 ANSI C 风格的函数定义:

void show_n_char(char ch, int num)

该行告知编译器 show_n_char() 使用两个参数 ch 和 num,ch 是 char 类型,num 是 int 类型。这两个变量被称为形式参数(formal argument,但是最近的标准推荐使用 formal paramete)),简称形参。和定义在函数中变量一样,形式参数也是局部变量,属该函数私有。这意味着在其他函数中使用同名变量不会引起名称冲突。每次调用函数,就会给这些变量赋值。
PS:ANSI C 要求在每个变量前都声明其类型。也就是说,不能像普通变量声明那样使用同一类型的变量列表:

void dibs(int x, y, z) /* 无效的函数头 */
void dubs(int x, int y, int z) /* 有效的函数头 */

声明带形式参数的函数

在使用函数之前,要用 ANSI C 形式声明函数原型:

void show_n_char(char ch, int num);

当函数接受参数时,函数原型用逗号分隔的列表指明参数的数量和类型。根据个人喜好,你也可以省略变量名:

void show_n_char(char, int);

在原型中使用变量名并没有实际创建变量,char 仅代表了一个 char 类型的变量,以此类推。

调用函数

在函数调用中,实际参数(actual argument,简称实参)提供了 ch 和 num 的值。

show_n_char(SPACE, 12);

实际参数是空格字符和 12。这两个值被赋给 show_n_char() 中相应的形式参数:变量 ch 和 num。简而言之,形式参数是被调函数(called function)中的变量,实际参数是主调函数(calling function)赋给被调函数的具体值。
实际参数可以是常量、变量,或甚至是更复杂的表达式。无论实际参数是何种形式都要被求值,然后该值被拷贝给被调函数相应的形式参数。被调函数不知道也不关心传入的数值是来自常量、变量还是一般表达式。再次强调,实际参数是具体的值,该值要被赋给作为形式参数的变量。因为被调函数使用的值是从主调函数中拷贝而来,所以无论被调函数对拷贝数据进行什么操作,都不会影响主调函数中的原始数据。
PS:实际参数是出现在函数调用圆括号中的表达式。形式参数是函数定义的函数头中声明的变量。调用函数时,创建了声明为形式参数的变量并初始化为实际参数的求值结果。

返回值

前面介绍了如何把信息从主调函数传递给被调函数。反过来,函数的返回值可以把信息从被调函数传回主调函数。
使用 return 语句可以返回值,返回值不仅可以赋给变量,也可以被用作表达式的一部分。
使用 return 语句的另一个作用是,终止函数并把控制返回给主调函数的下一条语句。

C语言 —— 函数介绍相关推荐

  1. C语言---函数介绍详解

    生活的全部意义在于无穷地探索尚未知道的东西,在于不断地增加更多的知识--左拉 文章目录 前言 函数 模块化程序设计方法 函数的定义 函数的分类 函数定义角度 库函数 自定义函数 函数形式角度 无参函数 ...

  2. str开头的c语言函数介绍,C语言str函数系列

    1.strcat() 此函数原型为 char *strcat(char *dest, const char *src). 功能为连接两个字符串,把src连接到dest后面:返回dest地址 实现如下 ...

  3. swift1.2语言函数和闭包函数介绍

    swift1.2语言函数和闭包函数介绍 在编程中,随着处理问题的越来越复杂,代码量飞速增加.其中,大量的代码往往相互重复或者近似重复.如果不采有效方式加以解决,代码将很难维护. swift1.2语言函 ...

  4. c语言 临时文件作用,c语言函数mktemp()产生唯一临时文件名实例源码介绍

    c语言函数mktemp()产生唯一临时文件名实例源码介绍.有关的函数:tmpfile引入的头文件:#include 定义函数mktemp():char * mktemp(char * template ...

  5. c语言复制粘贴源码,c语言函数memccpy()如何复制内存中的内容实例源码介绍

    c语言函数memccpy()如何复制内存中的内容实例源码介绍.引入的头文件:#include memccpy()函数定义:void * memccpy(void *dest, const void * ...

  6. R语言使用psych包进行主成分分析PCA和探索性因子分析EFA的常用函数介绍:principal、fa、fa.parallel、factor.plot、fa.diagram、scree

    R语言使用psych包进行主成分分析PCA和探索性因子分析EFA的常用函数介绍:principal.fa.fa.parallel.factor.plot.fa.diagram.scree 目录

  7. c语言比较函数memcmp,c语言函数memcmp()如何比较内存前n个字节实例源码介绍

    c语言函数memcmp()如何比较内存前n个字节实例源码介绍.引入头文件:#include 定义memcmp()函数:int memcmp (const void *s1, const void *s ...

  8. 2021-03-08 C语言strcasecmp函数和strncasecmp函数介绍和实例测试

    C语言strcasecmp函数和strncasecmp函数介绍和实例测试 一. strcasecmp()用来比较参数s1和s2字符串,比较时会自动忽略大小写的差异.若参数s1和s2字符串相同则返回0. ...

  9. libpcap c语言,libpcap库主要函数介绍

    libpcap是一个C语言库,libpcap的英文意思是 Packet Capture library,即数据包捕获函数库,其功能是通过网卡抓取网络以太网中的数据包.这个库为不同的平台提供了一致的c函 ...

最新文章

  1. java第三章_Java 第三章
  2. 蓝绿部署、金丝雀发布(灰度发布)、AB测试……
  3. android如何获取SHA1
  4. 每天一道LeetCode-----将有序序列转成高度平衡二叉搜索树
  5. pytorch 语义分割loss_vedaseg:基于pytorch的开源语义分割工具库,更多模型支持,更易拓展...
  6. valueChangeListener
  7. 编程语言之父6大经典名言,C语言之父这一段代码你见过吗?
  8. Scratch之猫和老鼠
  9. 矩阵的卷积以及使用python计算方法
  10. 苹果手机各种尺寸详细表以及iPhoneX、iPhoneXS、iPhoneXR、iPhoneXSMax、iPhone 11、iPhone 12、屏幕适配
  11. ASP.NET ZERO 学习 —— (4) 开发手册之AccountController
  12. TP5序列化和反序列化报错!缓存溢出
  13. DevExpress 控件中文化教程详解(内含下载官网中文化包和自定义修改中文化包制作教程)
  14. java合并图片合成多张横向或竖向
  15. 简述计算机程序执行过程,计算机程序的执行过程
  16. 电脑网络连接为什么常常连接不上
  17. 0202了,你会用手机操控电脑吗?
  18. 一流在线课程申报表公共计算机,衡阳财经业职业技术学院精品课程建设申报表.doc...
  19. 练习八:利用有限状态机进行时序逻辑的设计
  20. 计算机网络基础(类别 | 性能指标 | OSI模型初识)

热门文章

  1. 498.Diagonal Traverse-M
  2. Crypto++编译使用
  3. win10 开启全局代理
  4. zabbix常见问题
  5. R语言 substring() 函数 :提取字符串的一部分
  6. python面试大全 萧井陌_有多少人按@萧井陌大神给出的Python+Flask路线找到工作了?...
  7. 使用 Unity 和 C# 开发您的首个游戏
  8. Xcode7 Provisioning Profile
  9. 计算机网络教程试题库,计算机网络教程_复习题及答案.doc
  10. nmap扫描出错sendmsg: No route to host