8、函数
关键词:逐步分解、分而治之、模块化程序设计方法
1、函数概述
1、所谓函数其实就是一段可以重复调用的、功能相对独立完整的程序段。
2、从定义角度函数分为:标准库函数和用户自定义函数。
从函数兼有其他语言中的函数和过程的角度也可将其分为:有返回值函数和无返回值函数。
从主调函数和被调函数间数据传送的角度可分为:有参函数和无参函数。
3、在C语言中,所有的函数定义,包括主函数main在内,都是平行的。也就是说,在一个函数体内,不能再定义另一个函 数,即不能嵌套定义。但函数之间允许相互调用,也允许嵌套调用。
4、一个C语言源程序必须有也只能有一个主函数main。
2、函数的定义和调用
1、返回值类型可以是除数组类型外的任何类型。
2、对于一个有返回值的自定义函数来说,会有return语句,如果没有,也会返回一个值,但不可预知。
3、实参表求值顺序(即实参赋值给形参的顺序),一般从右至左。
4、函数有返回值的话,函数体内一般包含return(表达式); 或return表达式; 语句,不可用return; 语句形式返回。
3、函数参数的传递方式
1、函数参数的传递方式:值传递方式和地址传递方式。
4、变量的作用域和生存期
1、主函数main()中定义的变量也是局部变量,它只能在主函数中使用。
2、全局变量也称外部变量。它在函数外部定义的变量。属于源程序文件。生存期与程序相同。
3、一般不使用全局变量。在同一源文件中,允许局部变量和全局变量同名。在局部变量的作用域中,全局变量被屏蔽不 起作用,要引用全局变量,必须在变量名前加上两个冒号“ :: ”。
5、变量的存储类型
1、内存的区域划分:系统区(操作系统等)、用户区(程序区、静态存储区、动态存储区)。
2、全局变量全部放在静态存储区。
3、动态存储区用来存放变量以及进行函数调用时的现场信息和函数返回地址等。如:形参变量、函数体内部定义的动态 局部变量。
4、auto(自动型)、register(寄存器型)、extern(外部型)、static(静态型) 前两个为动态存储类型的变量,后两个 为静态存储类型的变量
5、自动型变量存储在动态存储区,属于动态存储类型;外部型变量和静态型变量存储在静态存储区,属于静态存储类 型;寄存器型变量存储在CPU的寄存器中。
- 自动变量只能在函数内或复合语句中定义,属于局部变量。
- 外部变量(存储)和全局变量(作用域)对同一类变量的两种不同角度的提法。它属于静态存储类型。
- 静态变量属于静态存储类型;但静态存储类型的变量不一定是静态变量。
- 静态局部变量在调用函数或执行复合语句之前就已经生成,退出函数或复合语句仍存在,变量保持现有的值,直到程序终止。也就是它的生存期为整个源程序。但其作用域与自动变量相同。退出函数或复合语句后不能再使用。意义?意义就是当再次调用定义它的函数时,它又可继续使用,而且保存了前次被调用后留下的值。
- 静态局部变量若在定义时未赋初值,则系统自动赋初值0,若定义时赋了初值,则赋初值操作在程序开始执行时就执行了,调用函数或执行复合语句时,不会执行赋初值操作。而对自动变量来说,如果定义时对变量赋初值,则每次调用函数或执行复合语句时都要执行赋初值操作。
- 非静态全局变量的作用域是整个源程序,当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中通过外部变量说明都是有效的。而静态全局变量则限制了其作用域,即只在定义该变量的源文件内有效,在同一源程序的其他源文件中不能通过外部变量说明来使用它。
- 把局部变量改变成静态变量后改变了它的存储方式,即改变了它的生存期。把全局变量改变从静态变量后是改变了它的作用域,限制了它的使用范围。
- 寄存器变量存放在cpu的寄存器中,使用时,不需要访问内存,而直接从寄存器中读写,这样可以提高效率。只有局部自动变量和形式参数才可以定义为寄存器变量。凡需要采用静态存储类型的量不能定义为寄存器变量。
6、函数的嵌套和递归调用
1、陷入细节是无法编写程序的。
7、函数的作用域
1、内部函数(static),也成为静态函数,在一个源文件中定义的函数只能被本文件中的函数调用,而不能被同一源程序 其他文件中的函数调用。
2、外部函数(extern),如果函数定义中没有说明static或extern,则隐含extern。
8、常用库函数
1、常用数学函数
- double fabs(double x);
- int abs(int x);
- long labs(long n);
- double sqrt(double x);
- double ceil(double x);
- double floor(double x);
- double pow(double x,double y); //x^y
2、常用字符处理函数
- int isalpha(int ch); //检查字符是否为字母 ctype.h 是字母返回非0
- int isupper(int ch); //检查字符是否为大写字母 只有大写的26个字母
- int islower(int ch);//检查字符是否为小写字母
- int isdigit(int ch);//检查字符是否为数字字符
- int isalnum(int ch);//检查字符是否为字母或数字字符
- int tolower(int ch);//将字符转换为小写字母
- int toupper(int ch);//将字符转换为大写字母
- int iscntrl(int ch);//检查字符是否为控制字符
3、常用字符串处理函数
- char *strupr(char *str);//转换为大写字符串 string.h 返回值为字符串str的首地址。
- char *strlwr(char *str);//转换为小写字符串
- char *strset(char *str,int c);//设置字符串中的字符
- char *strchr(const char *str,int c);//字符串中查找某字符
- char *strrchr(const char *str,int c);//字符串中反向查找某字符 找到返回第一个出现的地址,未找到返回NULL
- char *strstr(const char *str1,const char *str2);//字符串中查找子串 如果str2为空串,则返回str1的首地址
4、常用数据类型转换函数
- double atof(const char *str);//字符串转换为双精度浮点数 stdlib.h 如果字符串无法转换成双精度浮点数,则返回0。
- long atol(const char *str);//字符串转换为长整型数
- int atoi(const char *str);//字符串转换为整型数
- char *ultoa(unsigned long value,char *str,int radix);//无符号长整型数转换成任意进制的字符串
- int sprintf(char *str,const char *format,args,…);//格式化字符串转换 将输出列表args的值按format规定的格式输出到字符串str中。
易错:
1、如果函数值的类型与返回值类型不一致,以函数值类型为准。
2、如果形参和实参类型不一致,以形参类型为准。
3、全局变量的作用域与局部变量的作用域没有可比性。
4、C语言中形参默认存储类型是auto;函数隐含的存储类型是extern;局部变量隐含的存储类型是auto。
5、传值调用时,实参和与其对应的形参各占用独立的存储单元。