第五章 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函数就是 库函数

1589120-20190119193112300-871746841.png

5 自定义函数

就是用户在程序中自己编写的函数
定义语法:返回类型 函数名(参数列表)
{
函数体
}
 参数列表和返回类型对应着输入输出
函数名用于和程序中其他程序实体区分
而函数体是一段可执行的代码块,实现特定的算法或功能。

  • 注意

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

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

      6 函数调用

      分类:
      一是“先定义,后调用”,这要求函数定义和调用语句在同一个文件内,编译器能从函数定义中提取函数的参数列表、输出类型等接口信息。
      二是“函数声明+函数调用”,大多数情况下,函数的定义与函数的调用并不在一个文件内,即使在一个文件中也有可能调用在前而定义在后,这时需要在调用之前先对函数声明(声明可以有多个),告诉编译器有这么一个函数存在,函数原型声明将在后面讨论
      1589120-20190219150634589-1408739393.png
      【注】函数可以嵌套调用,调用的时候,只有这个函数执行完成,才会
      执行下一句

7 实际参数和形式参数

1589120-20190219150919872-271751378.png
1589120-20190219150936491-1311049025.png
实参a和形参a在内存中的并不是同一个地址。通过调用函数传递值并不能改变
实参的值。
例:
1589120-20190220102118733-395579472.png
结果是10

8 函数返回值

使用return语句,可以使函数向调用处返回一个值。

它有两个功能:
(1)立即从所在的函数体中退出,返回到调用它的程序中去,
(2)同时返回一个值给调用它的函数。

有两种常用方法可以让函数终止运行并返回到调用它的函数中去:
(1)当执行到函数的最后一条语句后返回
(2)当执行到语句return时返回。

1589120-20190219153132048-707082200.png
返回值类型被强制转换
1589120-20190219153253764-772122932.png

递归调用

在学习递归之前,先复习一下goto语句

1589120-20190219155757596-1125989794.png
运行结果:

1秒钟打印一次
1589120-20190219160613696-122820685.png
简单的递归调用
定义一个函数 calc,在其内部调用自己
1589120-20190219161449073-827066397.png
1589120-20190219161506765-1984184776.png
递归调用
1589120-20190219161548441-359592100.png

1589120-20190219164110541-334620591.png
Main函数中的代码是:

dosh(5);

运行结果:
1589120-20190219164145874-12335073.png
递归调用的分析图:
1589120-20190219164311217-368106502.png
通过递归实现数据相加
1589120-20190219164344712-928036599.png
Main函数的代码:
1589120-20190219164647919-1449932403.png
运行结果:
打印出15
相当于1+2+3+4+5 =15
1589120-20190219164719413-1001174543.png
递归调用的分析示意图:
1589120-20190219164746837-36521911.png
腾讯面试题:
有50个台阶,一次走一步,或者走两步,有多少种可能走完?
1589120-20190220163520643-1420323021.png
1589120-20190220163536407-303291343.png
[2] 通过变量值交换
1589120-20190220163610098-1435234503.png
[3]通过数组元素的值交换
1589120-20190220163639112-1596494010.png
Main函数
1589120-20190220163659332-1734094135.png
运行结果:
1589120-20190220163714422-1018275968.png
通过递归调用把十进制转换为二进制
1589120-20190220163806966-586889282.png
在main函数中调用change2:
1589120-20190220163834364-53597210.png
运行结果如图所示:

十进制的10转换成二进制后为1010
1589120-20190220163852605-1789284349.png

函数小结面向过程的程序结构

任何一个大于4的偶数,都可以被拆解为两个质数

(我们通过面向过程的模块化编程来求解一下)

(1) 编写一个模块用来判断一下一个数是否是质数
1589120-20190220164023258-423483129.png
1589120-20190220164034716-908051060.png
(2)Main函数调用 自定义的函数模块
1589120-20190220164056453-719001416.png
1589120-20190220164120687-356544775.png
1589120-20190220164139610-1752613364.png
1589120-20190220164159713-427077492.png
1589120-20190220164222225-1448438035.png
1589120-20190220164240541-1655633913.png
keybd_event 函数功能:该函数合成一次击键事件。系统可使用这种合成的击键事件来产生WM_KEYUP或WM_KEYDOWN消息,键盘驱动程序的中断处理程序调用keybd_event函数。
1589120-20190220164353134-1881901459.png
1589120-20190220164407171-113690077.png
5.1.31习题

1、 设计一个函数,判断整数有多少位?

解题代码如下:

定义一个函数,形参是data,每次都使data/=10 ,定义一个length使他自增,直到data==0为止,计算出data的位数,用length作为返回值。

1589120-20190220164641140-957079175.png

在main函数中调用wei这个函数。
1589120-20190220164652187-1979674286.png

运行结果:

输入123456。 打印出位数为6

1589120-20190220164701814-492141272.png

2、 设计一个函数,检测一个数是否为质数

定义一个函数zhi ,用于判断是否为质数,如果为质数,返回
1,否则返回0
1589120-20190220164727169-960195586.png
1589120-20190220164736500-414494138.png
return flag;
}

在main函数中输入如下代码进行测试

1589120-20190220164753724-25921954.png

运行结果:

    输入10,不是质数
     
输入2,是质数

注:

  • 1 局部变量,调用完成以后会被回收。
    局部变量是为块语句服务,块语句执行结束,局部变量就会被回收。
    函数内部定义的变量,还有函数的参数都是局部变量。
  • 2 全局变量,不属于任何一个函数。可以被任何一个函数调用。
    创建全局变量比main函数还要早,全局变量会一直占内存,而局部变量,用完就扔。
    需要谁都可以访问的场合就需要全局变量。全局变量可以用于函数的通信
  • 3 块语句内部的变量,作用域是整个语句中从定义开始到结束,也可以作用与内部包含的块语句,但是遇到同名变量会被屏蔽。同一个块语句,不能定义重名变量。
  • 4 全局变量可以被所以函数所共享。全局变量的作用域就是全局
    使用全局变量要注意:
    • 1、名字要容易理解,尽可能不与局部变量重名
    • 2、避免占内存较大的变量使用全局变量,节约内存
    • 3、避免全局变量被错误的修改
      正规的软件工程,写一个函数要修改全局变量,一定要注释。
      为什么修改,修改的目的是什么,修改值是多少。
  • 5调用一个函数,必须知道有这个函数,C语言从上往下开始编译。
    上面如果没有函数的定义,或者声明就无法找到函数,无法调用。
    函数在调用之前,编译器从函数定义中挖掘函数声明。
    如果在调用之后,需要在调用之前加上函数声明。
    函数的声明,只是说明函数的存在,所以可以有多个.

    函数可变参数(涉及到部分指针)

    1589120-20190221101616732-1829405925.png
    1589120-20190221101555290-69600087.png
    1589120-20190221101710017-782593782.png

1589120-20190221102534265-390690266.png
1589120-20190221102723586-1517653295.png

函数求参数顺序

1589120-20190221103614973-1485012798.png
1589120-20190221103709255-1447959008.png
函数从右向左
1589120-20190221103952156-931824601.png
1589120-20190221104038249-1614092256.png
gcc也是从右向左

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

1589120-20190221104953502-521063877.png

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

转载于:https://www.cnblogs.com/xingkongcanghai/p/10293008.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值