第五章 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. 函数需要有实体(当我们编译的时候通常会出现这样一个错误提示:
      【 1个无法解析的外部命令 】 出现的 原因通常是因为没有函数的实体

    2. 函数不能怀孕(嵌套)

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也是从右向左

函数返回值生命周期 与 函数副本机制


但是如果返回全局变量,就会一直存在
数组没有副本机制,机构体变量有副本机制,
结构体变量内部有数组也有副本机制

posted @ 2019-01-19 19:33  星空与沧海  阅读(268)  评论(0编辑  收藏  举报