当前位置: 首页 > news >正文

【时时三省】(C语言基础)对被调用函数的声明和函数原型

山不在高,有仙则名。水不在深,有龙则灵。 ----CSDN 时时三省

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

( 1 )首先被调用的函数必须是已经定义的函数(是库函数或用户自己定义的函数),但仅有这一条件还不够。

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

例如:

# include < stdio.h >

其中,“stdio.h”是一个“头文件”。在stdio.h文件中包含了输入输出库函数的声明。如果不包含“stdio.h”文件,就无法使用输入输出库中的函数。同样,使用数学库中的函数,应该用# include < math.h >。h是头文件所用的后缀,表示是头文件(headerfile)。

( 3 )如果使用用户自己定义的函数,而该函数的位置在调用它的函数(即主调函数)的后面(在同一个文件中),应该在主调函数中对被调用的函数作声明(declaration)。声明的作用是把函数名、函数参数的个数和参数类型等信息通知编译系统,以便在遇到函数调用时,编译系统能正确识别函数并检查调用是否合法。

例题:

输入两个实数,用一个函数求出它们之和。

解题思路:

两个数相加的算法很简单。现在用add函数实现它。首先要定义add函数,它为float型,它应有两个参数,也应为float型。特别要注意的是:要对add函数进行声明。

编写程序:

运行结果: 

 

这是一个很简单的函数调用,函数add的作用是求两个实数之和,得到的函数值也是实型。程序第3行是对被调用的add函数作声明:

float add ( float x , float y ) ;

从程序可以看到:main函数的位置在add函数的前面,而程序进行编译时是从上到下逐行进行的,如果没有对函数add的声明,当编译到程序第7行时,编译系统无法确定add是不是函数名,也无法判断实参( a和b )的类型和个数是否正确,因而无法进行正确性的检查。

如果不作检查,在运行时才发现实参与形参的类型或个数不一致,出现运行错误。但是在运行阶段发现错误并重新调试程序,是比较麻烦的,工作量也较大。应当在编译阶段尽可能多地发现错误,随之纠正错误。

现在,在函数调用之前对add作了函数声明。因此编译系统记下了add函数的有关信息,在对“c = add ( a,b );”进行编译时就“有章可循”了。编译系统根据add函数的声明对调用add函数的合法性进行全面的检查。如果发现函数调用与函数声明不匹配,就会发出出错信息,它属于语法错误。用户根据屏幕显示的出错信息很容易发现和纠正错误。

可以发现,函数的声明和函数定义中的第1行(函数首部)基本上是相同的,只差一个分号(函数声明比函数定义中的首行多一个分号)。因此写函数声明时,可以简单地照写已定义的函数的首行,再加一个分号,就成了函数的“声明”。

函数的首行(即函数首部)称为函数原型( function prototype )。为什么要用函数的首部来作为函数声明呢?这是为了便于对函数调用的合法性进行检查。因为在函数的首部包含了检查调用函数是否合法的基本信息(它包括了函数名、函数值类型、参数个数、参数类型和参数顺序),在检查函数调用时要求函数名、函数类型、参数个数和参数顺序必须与函数声明一致,实参类型必须与函数声明中的形参类型相同(或赋值兼容,如实型数据可以传递给整型形参,按赋值规则进行类型转换)。否则就按出错处理。这样就能保证函数的正确调用。

说明:

使用函数原型作声明是C的一个重要特点。用函数原型来声明函数,能减少编写程序时可能出现的错误。由于函数声明的位置与函数调用语句的位置比较近,因此在写程序时便于就近参照函数原型来书写函数调用,不易出错。实际上,在函数声明中的形参名可以省写,而只写形参的类型,如上面的声明可以写为

float add ( float , float );/ /不写参数名,只写参数类型

编译系统只关心和检查参数个数和参数类型,而不检查参数名,因为在调用函数时只要求保证实参类型与形参类型一致,而不必考虑形参名是什么。因此在函数声明中,形参名可写可不写,形参名是什么都无所谓,如:

float add ( float a , float b );/ /参数名不用x,y,而用a,b。合法

根据以上的介绍,函数声明的一般形式有两种,分别为

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

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

有些专业人员喜欢用不写参数名的第(2 )种形式,显得精练。有些人则愿意用第(1 )种形式,只须照抄函数首部就可以了,不易出错,而且用了有意义的参数名有利于理解程序,如:

void print ( int num , char sex , float score );

大体上可猜出这是一个输出学号、性别和成绩的函数,而若写成

void print ( int , float , char ) ;

则无从知道形参的含义。

注意:

对函数的“定义”和“声明”不是同一回事。函数的定义是指对函数功能的确立,包括指定函数名、函数值类型、形参及其类型以及函数体等,它是一个完整的、独立的函数单位。而函数的声明的作用则是把函数的名字、函数类型以及形参的类型、个数和顺序通知编译系统,以便在调用该函数时系统按此进行对照检查(例如,函数名是否正确,实参与形参的类型和个数是否一致),它不包含函数体。

如果已在文件的开头(在所有函数之前),已对本文件中所调用的函数进行了声明,则在各函数中不必对其所调用的函数再作声明。例如:

char letter ( char , char ) ;

float f ( float , float ) ;

int i ( float , float ) ;

int main ( )

{

...

}

/ /下面定义被main函数调用的3个函数

char letter ( char c1 , char c2 )

{

...

}

float f ( float x , float y )

{

...

}

int i ( float j , float k )

{

...

}

由于在文件的开头(在函数的外部)已对要调用的函数进行了声明(这些称为“外部的声明”),因此在程序编时,编译系统已从外部声明中知道了函数的有关信息,所以不必在主调函数中再重复进行声明。写在所有函数前面的外部声明在整个文件范围中有效。

 

 

相关文章:

  • [特殊字符] GUNION SDK 接口调用方式说明(静态库 vs 动态库)
  • C/C++的OpenCV 进行图像梯度提取
  • 并发容器(Collections)
  • bi软件是什么?bi软件是做什么用的?
  • 量化研究---bigquant策略交易api研究
  • 30个性能优化方案
  • Python在自动驾驶中的多传感器融合——让智能汽车“看得更清楚”
  • Ubantu安装 Jenkins LTS
  • VR全景制作方法都有哪些?需要注意什么?
  • 9大开源AI智能体概况
  • 香港维尔利健康科技集团全面推进AI医疗落地,构建智慧健康管理新模式
  • Honeywell 05701-A-0302 单通道控制卡
  • 机器学习第二十四讲:scikit-learn → 机器学习界的瑞士军刀
  • 响应面分析之最速上升法
  • 使用vscode MSVC CMake进行C++开发和Debug
  • 职坐标解析物联网协议与传感器技术实战应用
  • Spring Boot微服务架构(一):如何拆分?如何将CRM系统拆解为多个微服务构建?
  • python之数据结构与算法篇
  • 【萤火工场GD32VW553-IOT开发板】ADC电压表
  • 在 Docker 中启动 Jupyter Notebook
  • 做纯净系统的网站/关键词包括哪些内容
  • 企业内部系统网站制作/百度推广app下载
  • 重庆市工程安全建设信息网官网/深圳百度seo整站
  • 厦门外贸网站建设哪家公司大/媒体公关公司
  • 企业网站建设ppt介绍/网络营销的定义是什么
  • 太湖网站建设推荐秒搜科技/aso安卓优化