第六章 函数
一、函数的分类与定义
1、 函数的分类
从C 语言程序的结构上划分,C 语言函数分为主函数main( )和普通函数两种,而对于普通函数,又可以分为标准库函数和用户自定义函数。
1)标准库函数
标准库函数是由C 编译系统提供的库函数,在C 编译系统中将一些独立的功能模块编写成公用函数,并将它们集中存放在系统的函数库中,供程序设计时使用,称之为标准库函数。
丰富的可直接调用的库函数是C51功能及其高效率的重要体现之一,多使用库函数使程序代码简单,结构清晰,易于调试和维护 。
C51几类重要库函数及简要说明
对于标准C中原有的,在此不再说明,如MATH.H中的各数学运算函数。
① 专用寄存器include文件
包括了所有8051的SFR及其位定义,一般系统都必须包括本文件。如REG51.H ,AT89X51.H等。
② 绝对地址文件absacc.h, 见P337
该文件中实际只定义了几个宏,以确定各存储空间的绝对地址,如定义了XBYTE宏,允许用户访问8051外部数据存储器中的某一字节。
③存储器分配函数,位于stdlib.h中,见P340表B-11.
④字符串操作函数位于“string.h”中,见P341
其中包括拷贝比较移动等函数如:
memccpy、memchr、memcmp、memcpy、memmove、memset
这些函数 对缓冲区进行处理很方便。
memccpy、memchr、memcmp、memcpy、memmove、memset
这些函数 对缓冲区进行处理很方便。
⑤ 流函数输入输出,位于“stdio.h”中,见P344。
流函数缺省为8051串口,如要修改,比如改为LCD显示,可修改lib目录中的 getkey.c及putchar.c源文件,然后在库中替换它们即可定义用户的I/O口数 据读写。
2)用户自定义函数
用户自定义函数是用户根据自己的需要而编写的函数。从函数定义的形式上可以将其划分无参数函数、有参数函数和空函数。
无参数函数被调用时,既无参数输入,也不返回结果给调用函数,它是为完成某种操作而编写的函数。有参数函数在被调用时,必须提供实际的输入参数,必须说明与实际参数一一对应的形式参数,并在函数结束时返回结果供调用它的函数使用。定义空函数的目的是为了以后程序功能的扩充。
2、函数的定义
C51对函数的功能进行了扩展,函数定义的完整形式如下:
返回数据类型 函数名(形式参数列表) [reentrant] [interrupt n] [using m]{函数体;}
(注意对于原型函数的说明,和定义函数相似,但无函数体,也不能说明工作寄存器组的切换using n和中断说明interrupt函数。)
其中:
1)函数类型
有静态函数和外部函数。
C语言程序可以由多个函数组成,这些函数可以在同一个程序文件中,也可以在多个不同的程序文件中。根据这些函数的使用范围,可以把它们分为静态函数和外部函数。
静态函数(内部函数)
静态函数只能在定义它的文件中被调用,而不能在其他文件中的函数所调用。
外部函数(默认)
外部函数可以在定义它的文件和其它文件中被调用。可以在函数定义和调用时使用extern说
明是外部函数。但必须注意:在一个文件中,若将主程序放到前面,对后面出现的函数,就必须在文件开始进行说明,说明方式同普通C语言。否则出现警告如下:
函数**.C(5): warning C206: 'func': missing function-prototype
所以编程时,要习惯将main()放到最后。
(见“外部函数”)
例:
文件1:
#include<AT89X51.H>
extern add(x1,x2);c51中字符串函数
unsigned char data x1=12,x2=2,y;
main()
{
y=add(x1,x2);
}
文件2:
data char x3;
add(x1,x2)
{
x3=x1+x2;
return x3;
}
2)返回数据类型和函数返回值
如果返回数据,进行说明;如果不返回,一般用void说明,也可以不说明。
函数返回值通过return x返回,返回值是通过函数名带回的,所以一个函数只能有一个返回值。上例中的x3和y。
3)形参与实参
形参:在定义函数时,函数名后面括号中的变量称为“形参”,定义时不赋值,由调用函数将值传过来。
实参:主调用函数后面括号中的表达式为“实参”,实参必须有确定的值。该值在调用时按对应关系传递给形参。
C语言中参数传递是单向的。
4) 可重入函数
可重入函数可以在同一个时刻由多个进程共享。当一个进程正在执行一个可重入函数,另一个进程可以中断该进程,并可以开始执行同一个可重入函数,而不影响函数的运行结果。
因为8051 内部堆栈空间的限制,为了提高效率,C51 没有提供这种堆栈,而是提供一种压缩栈。每个函数有一个给定存储空间,用于存放局部变量。函数中的每个变量都存放在这个空间的固定位置。当递归调用该过程时会导致变量被覆盖,所以通常情况下C51中的函数是不能重入的。
可重入函数为此必须使用reentrant函数属性来声明函数是可重入的。
与不可重入函数的参数传递和局部变量的存储分配方法不同,C51编译器为再入函数生成一个模拟栈,通过这个模拟栈来完成参数传递和存放局部变量。这样每次函数调用时的局部变量都会被单独保存,再入函数一般占用较大的内存空间,运行起来也比较慢,并且不允许传递bit 类型的变量,也不能定义局部位变量。
可重入函数经常在实时应用系统中应用,也可在中断函数和非中断函数同时调用同一个函数时使用。
5) 规定函数使用的寄存器组切换using m
可使用using函数说明属性来规定函数所使用的寄存器组。
m是一个0-3的整形参数,分别对应0-3组工作寄存器。这个参数表示使用的寄存器组的编号,这个参数不能使用带运算符的表达式。using属性只能在函数定义中使用,不能在函数原型声明中使用。
使用using属性的函数将自动完成以下操作:
进入函数前,将当前使用的寄存器组的标号保存在堆栈中。
更改PSW的寄存器组选择位,选择设定的寄存器组作为当前的寄存器组。
函数退出时,将寄存器组恢复成进入函数前的寄存器组。
6) 中断函数说明interrupt n
C51最大支持32个中断,在单片机中n常用0-5。对应中断源见P177。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论