七、函数(基本概念)

1.函数, 具体逻辑功能(与数据<局部静态变量>)的载体,通过输入参数,进行内部黑箱操作,最后产生一个结果<直接消化,或者返回值

(可能一个数据,也可能是一批数据。可能通过return,也可能通过形参的间接方式<如形参是指向内存的一个首地址>)给调用用户>

2.函数声明和调用

声明:是对编译器宣告有这么一个函数,它的返回值及形参变量的类型是怎样的,函数名是什么,

即使函数体编译器还没有见到,它也可以先对调用这样的函数的语句编译放行。

隐式声明如果一个函数被调用前连声明都没有,C编译器也能放行,不过返回值类型就只能是int类型。(C++不再支持隐式声明

调用函数:运行使用指定函数名的函数,一般伴随参数的传递和返回值的接收过程。(主调函数<相对于被调用的函数来说>和被调函数)

C语言中函数名在程序中一般必须是唯一的。也必须遵守标识符命名规则。

UNIX一切函数都能调用自己,函数名代表了函数的首地址。

3.函数的格式:

声明:  返回值类型 函数名(形参列表<形参类型1,形参类型2…>);

只有参数类型,没有变量名的称为哑元,它只提供类型信息,眼前不需要使用,常用于声明或提供兼容作用。

void:没有返回值;  void* 未确定实际数据类型的指针变量。

定义实现:  返回值类型 函数名(形参列表<形参类型 变量1,形参类型 变量2…>){ 多个语句;}

4.函数参数的传递和值返回

函数的形参列表内的变量调用顺序自右向左,形参变量的空间分配是自左向右。

函数实参向形参的传递本质上是值的拷贝。拷贝目标是实参,拷贝的目的地是形参变量。形参变量得到的值其实是一个实参变量值的副本(存值的空间不同)。

变量在函数体中是自下向上,自右向左分配空间。变量在函数体中的定义及初始向是自左向右。(与形参的两种顺序刚好相反) 

当函数定义没有返回值类型,甚至连void也没有,这时C语言会默认处理为返回int类型(C++没有返回值的一般是特殊函数,如构造函数和析构函数)

5.可变参数的函数实现

类似printf(),scanf()这样的函数,里边的参数个数是不定(限制条件:至少会有一个确定的参数<指定数据类型的参数,在形参列表里靠左放置>)。

例:printf(): ”%d%c%f” //格式字符串里:1.每一个可变参数是什么类型,2.整体到底有多少个可变参数

一般参数列表是确定的,定义时有多少个形参,调用时就必须提供多少个实参,顺序要一样,指定实参与形参对应的数据类型也要一致(可强制转换类型也可以)。

实现可变参数函数,需要用到一个类库,头文件是stdarg.h

va_list:结构类型 //可用来定义一个存储指向可变形参列表的结构变量

va_start,va_arg,va_end 三个宏

va_start:告诉VA类库到底可变参数是由哪一个固定参数之后才开始(后边都是可变参数)。

va_arg:获取当前的可变参数结构变量里的一个参数值,并且结构变量内部的位置指针向后自动推进一位(下一次再调用va_arg,得到的就是下一个参数值)。

va_end: 结束操作,释放资源 

6.变量的作用域

C的标识符作用域就三种:局部(不单指函数,还包括内部的像循环体等{}内的作用域),全局(一般指放在函数外边的一些变量),文件(对应文件名的.c和.h所组成的功能单位)。

作用域:它决定了程序中的哪些语句可以使用该变量,或函数,结构体等等对象

各种同名变量作用域的优先顺序:下层花括号语句体>>上层函数体>>全局/文件(优先级高的屏蔽低的同名变量)

生命期:全局>文件>函数>下层花括号语句体

7.变量的存储类型

自动(auto)<生命结束时,有系统善后,自动由系统回收(内存空间的回收:只是登记这片空间已是空闲状态,并没有去清除空间所存的内容值)内存空间资源,编译器默认变量就是auto类型>

静态(static)<生命期如本进程>

外部(extern)<同上>

寄存器(register)<除了程序无法得到其内存地址,其余和自动变量一样><递交申请为VIP身份这样的含义>

const 只读,加了这个关键字,变量的空间就只能读不能写,那唯一的一次写的机会是在变量的初始化时.

volatile 易变的(实时更新), 不需要进行优化处理,一有变化,不要保留,马上反映.

 

8.递归函数

递归的意思是函数自己调用自身(直接方式),或者在自己函数调用的下级函数中又调用自己(间接方式)。

递归:可拆分为递(向下层传递参数)和归(函数不再向下传递时会一层一层的返回)两个过程

写递归函数需考虑的要素:

a.怎样取一个变量或多个往下递归(不是绝对,但是推荐这么做,变量在传递中要有变化)

b.样终止递归,要设置一个合理的终止条件(原来的规律不能成立,函数体递归前的代码不再能重复)

c.递归过程中的暂时或中间结果怎样保存(例:递归函数的局部静态变量<变得更高效和精简>,或用一个变量参数将它再传下去),不是每一个递归都需考虑这个情况。

注:递归函数没有限制函数体里可以调用多少次自身,但是物理硬件决定了它还是会有一个极限,尽量不要超过26万次(UNIX).

在一个递归函数体内部可有多种的归递调用副本,每一个副本传递的参数不同.

递归思维(怎样用递归解决复杂的有规律可寻的这样的一些问题):

A.找到一个解决有规律问题方案的一个典型环节(层面), 只考虑这一个环节(层面)的代码应该如何实现.

B.在这个环节(层面)里又只需考虑:

a.参数变量如何设置,如何变化传递.

b.终止条件语句如何写, 也就是不再遵守典型规律的那些情况如何变成代码上的终止条件.

c.仔细调整一下需输出的文字信息(放在递在过程和归的过程的情况,不要出现重复打印的情况).

结论: 递归思维本质特点是暂时忽略各个层次实现的不同细节,而只需关注固定的某一环节的较大的过程实现即可. (有规律性的,例外情况不会太多的问题,适合用递归来实现.)


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值