34.函数的本质及基本使用

来源:互联网 发布:淘宝商家贷款条件 编辑:程序博客网 时间:2024/06/01 09:09

34.1.函数的作用及书写规则
(1)整个程序分为多个源文件,每个源文件分为多个函数,每个函数分为多条语句,形成了整个程序的组织架构(源文件->函数->语句,有利于分化问题、便于编写程序、有利于多人协同合作);函数的发明是人(程序员和架构师)的需要(人的组织能力有限),而不是机器(编译器、CPU)的需要;函数的目的是实现模块化编程,即为了提供程序的可移植性。
(2)函数的格式为函数的返回类型、函数名、参数列表等;函数不能太长也不宜太短,原则是1个函数只能做1件事;函数传参不宜过多,在ARM体系下,传参不宜超过4个,超过4个则通过结构体打包,然后使用结构体指针传参;在函数内部尽量少碰全局变量,最好使用传参、返回值和外部交换数据,不要使用全局变量。


34.2.函数和变量的关系
(1)函数将来被编译成可执行代码段,变量(主要指全局变量)经过编译后变成数据或者在运行时变成数据,程序的运行需要代码和数据共同结合才能完成。
(2)代码和数据需要彼此配合,代码是为了加工数据,数据必须借助代码来起作用(数据是原材料,代码是加工流水线);名词性的数据必须经过动词性的加工才能变成最终我们需要的产出的数据,这个加工的过程即程序的执行过程。
(3)在面相对象中分别叫方法和成员,某个类中的属性可以通过成员表示,而动作可以通过方法表示,我们通过方法和成员可以描述某个类的所有特性。


34.3.函数即数据处理器
(1)程序运行的主要目标是生成目标数据;我们必须通过原材料+加工算法得到目标数据,原材料即程序的输入数据,加工算法即程序;程序的编写和运行即为了把原数据加工成目标数据,则程序的实质就是数据处理器。
(2)函数就是程序的缩影,函数的参数列表即输入原材料数据,函数的返回值和输出型参数即输出目标数据,函数的函数体里的那些代码即加工算法。
(3)函数在静止没有执行时只占用存储空间并不占用资源(CPU+内存);函数的运行需要耗费资源(CPU+内存);函数运行时可以对数据加工生成目标数据,函数运行完毕会释放占用的资源。
(4)整个程序的运行其实就是很多个函数相继运行的连续过程。


34.4.函数的三要素
(1)函数三要素(定义、声明、调用),函数的定义就是函数体、函数声明是函数原型、函数调用就是使用函数。
(2)函数定义是函数的根本,函数定义中的函数名即该函数在内存中的首地址,所以可以用函数名来调用执行这个函数(实质是指针解引用访问);函数定义中的函数体是函数的执行关键,函数将来执行时主要就是执行函数体。
(3)函数声明的主要作用是告诉编译器函数的原型;函数调用就是调用执行某个函数。


34.5.函数的原型和作用
(1)函数原型就是函数的声明(函数的函数名、返回值类型、参数列表);函数原型的主要作用就是给编译器提供原型,让编译器在编译程序时帮我们进行参数的静态类型检查。
(2)编译器是以单个源文件为单位编译程序的(函数在哪里调用就必须在哪里声明);编译器工作时源文件已经经过预处理了(宏定义全部替换、头文件包含全部原地展开);编译器编译文件时是按照文件中语句的先后顺序进行编译处理的。
(3)编译器从源文件的第1行开始编译,遇到函数声明时就会收到编译器的函数声明表中,然后继续向后;当遇到1个函数调用时,就在编译器的本文件的函数声明表中去查这个函数,看有没有原型相对应的函数(有且只能有1个);如果没有或者只有部分匹配则会报错或报警告;如果发现多个则会报错或报警告(C语言中不允许2个函数原型完全1样,该过程是在编译器遇到函数定义时完成的,则函数可以重复声明但是不能重复定义)。


34.6.递归函数及递归调用原理
(1)递归函数就是函数中调用了该函数本身的函数;递归不等于循环;递归函数解决的典型问题为求阶乘、求斐波那契数列。
(2)实际上递归函数是在栈内存上递归执行的,每次递归执行1次就需要耗费一些栈内存;栈内存的大小是限制递归深度的重要因素。
(3)递归收敛性:递归函数必须有1个终止递归的条件,当每次该函数被执行时,我们判断某个条件决定是否继续递归,该条件最终必须能够被满足,若没有递归终止条件或该条件永远不能被满足,则该递归没有收敛性,其最终要失败;
(4)递归栈溢出:因为递归是占用栈内存的,每次递归调用都会消耗一些栈内存,因此必须在栈内存耗尽之前递归收敛(终止),否则就会栈溢出,递归有风险,使用需谨慎。


34.recursive/* * 公司:XXXX * 作者:Rston * 博客:http://blog.csdn.net/rston * GitHub:https://github.com/rston * 项目:函数的本质及基本使用 * 功能:演示递归实现阶乘和斐波那契数列。 */#include <stdio.h>int main(int argc, char **argv){    int a = 5;    // The factorial of 5 is 120.    printf("The factorial of %d is %d.\n", a, factorial(a));        int b = 3;    // The 3th's value of fibonacci is 2.    printf("The %dth's value of fibonacci is %d.\n", b, fibonacci(b));    return 0;}// 阶乘int factorial(int n){    if (n < 1)    {        printf("The value of n must >= 1.\n");        return -1;    }    if (1 == n)    {        return 1;    }    else     {        return (n * factorial(n-1));    }}// 斐波那契数列int fibonacci(int n){    if (n < 0)    {        printf("The value of n must >= 0.\n");        return -1;    }    else if (0 == n)    {        return 0;    }    else if ((1==n) || (2==n))    {        return 1;    }    else    {        return (fibonacci(n-1) + fibonacci(n-2));    }}

1 0