第五章 1 函数
1 函数的作用
函数可以把相对独立的某个功能抽象出来,使之成为程序中的一个独立实体,可以在同一个程序或其他程序中多次重复使用
2 例子
模拟键盘操作
#include<stdio.h>
#include<Windows.h>
void main() {
keybd_event(0x5b, 0, 0, 0);//按下win
keybd_event('R', 0, 0, 0);//按下R
keybd_event('R', 0, 2, 0);//松开R
keybd_event(0x5b, 0, 2, 0);//松开win
}
3 函数的分类:
- 无参函数:
通常用来执行一些功能比较单一的语句
- 有参函数:
通常通过处理传递过来的参数,将函数值返回给调用处
4 库函数:
库函数分为 标准库函数(如stdio.h) 和 第三方库函数(Windows.h)
- 库函数的特点:
* 由c语言系统提供
* 用户无须定义,也不必在程序中做类型说明
* 只需在程序前写出包含有该函数定义的头文件
例如 system函数就是 库函数
5 自定义函数
就是用户在程序中自己编写的函数
定义语法:返回类型 函数名(参数列表)
{
函数体
}
参数列表和返回类型对应着输入输出
函数名用于和程序中其他程序实体区分
而函数体是一段可执行的代码块,实现特定的算法或功能。
-
注意
-
函数需要有实体(当我们编译的时候通常会出现这样一个错误提示:
【 1个无法解析的外部命令 】 出现的 原因通常是因为没有函数的实体
) -
函数不能怀孕(嵌套)
-
6 函数调用
分类:
一是“先定义,后调用”,这要求函数定义和调用语句在同一个文件内,编译器能从函数定义中提取函数的参数列表、输出类型等接口信息。
二是“函数声明+函数调用”,大多数情况下,函数的定义与函数的调用并不在一个文件内,即使在一个文件中也有可能调用在前而定义在后,这时需要在调用之前先对函数声明(声明可以有多个),告诉编译器有这么一个函数存在,函数原型声明将在后面讨论
【注】函数可以嵌套调用,调用的时候,只有这个函数执行完成,才会
执行下一句
7 实际参数和形式参数
实参a和形参a在内存中的并不是同一个地址。通过调用函数传递值并不能改变
实参的值。
例:
结果是10
8 函数返回值
使用return语句,可以使函数向调用处返回一个值。
它有两个功能:
(1)立即从所在的函数体中退出,返回到调用它的程序中去,
(2)同时返回一个值给调用它的函数。
有两种常用方法可以让函数终止运行并返回到调用它的函数中去:
(1)当执行到函数的最后一条语句后返回
(2)当执行到语句return时返回。
返回值类型被强制转换
递归调用
在学习递归之前,先复习一下goto语句
运行结果:
1秒钟打印一次
简单的递归调用
定义一个函数 calc,在其内部调用自己
递归调用
Main函数中的代码是:
dosh(5);
运行结果:
递归调用的分析图:
通过递归实现数据相加
Main函数的代码:
运行结果:
打印出15
相当于1+2+3+4+5 =15
递归调用的分析示意图:
腾讯面试题:
有50个台阶,一次走一步,或者走两步,有多少种可能走完?
[2] 通过变量值交换
[3]通过数组元素的值交换
Main函数
运行结果:
通过递归调用把十进制转换为二进制
在main函数中调用change2:
运行结果如图所示:
十进制的10转换成二进制后为1010
函数小结面向过程的程序结构
任何一个大于4的偶数,都可以被拆解为两个质数
(我们通过面向过程的模块化编程来求解一下)
(1) 编写一个模块用来判断一下一个数是否是质数
(2)Main函数调用 自定义的函数模块
keybd_event 函数功能:该函数合成一次击键事件。系统可使用这种合成的击键事件来产生WM_KEYUP或WM_KEYDOWN消息,键盘驱动程序的中断处理程序调用keybd_event函数。
5.1.31习题
1、 设计一个函数,判断整数有多少位?
解题代码如下:
定义一个函数,形参是data,每次都使data/=10 ,定义一个length使他自增,直到data==0为止,计算出data的位数,用length作为返回值。
在main函数中调用wei这个函数。
运行结果:
输入123456。 打印出位数为6
2、 设计一个函数,检测一个数是否为质数
定义一个函数zhi ,用于判断是否为质数,如果为质数,返回
1,否则返回0
return flag;
}
在main函数中输入如下代码进行测试
运行结果:
输入10,不是质数
输入2,是质数
注:
- 1 局部变量,调用完成以后会被回收。
局部变量是为块语句服务,块语句执行结束,局部变量就会被回收。
函数内部定义的变量,还有函数的参数都是局部变量。 - 2 全局变量,不属于任何一个函数。可以被任何一个函数调用。
创建全局变量比main函数还要早,全局变量会一直占内存,而局部变量,用完就扔。
需要谁都可以访问的场合就需要全局变量。全局变量可以用于函数的通信 - 3 块语句内部的变量,作用域是整个语句中从定义开始到结束,也可以作用与内部包含的块语句,但是遇到同名变量会被屏蔽。同一个块语句,不能定义重名变量。
- 4 全局变量可以被所以函数所共享。全局变量的作用域就是全局
使用全局变量要注意:- 1、名字要容易理解,尽可能不与局部变量重名
- 2、避免占内存较大的变量使用全局变量,节约内存
- 3、避免全局变量被错误的修改
正规的软件工程,写一个函数要修改全局变量,一定要注释。
为什么修改,修改的目的是什么,修改值是多少。
- 5调用一个函数,必须知道有这个函数,C语言从上往下开始编译。
上面如果没有函数的定义,或者声明就无法找到函数,无法调用。
函数在调用之前,编译器从函数定义中挖掘函数声明。
如果在调用之后,需要在调用之前加上函数声明。
函数的声明,只是说明函数的存在,所以可以有多个.
函数可变参数(涉及到部分指针)
函数求参数顺序
函数从右向左
gcc也是从右向左
函数返回值生命周期 与 函数副本机制
但是如果返回全局变量,就会一直存在
数组没有副本机制,机构体变量有副本机制,
结构体变量内部有数组也有副本机制