模块化设计:
1)C程序全部由函数构成,它提供所有程序活动的场所
2)要学会合理地划分程序中的各个模块。在设计一个大型的商业程序时候,可以采用一种好的策略,即把一个大的程序分割成一些相对独立,且便于管理和阅读的小块程序。关键是把它分散成若干个小块(模块),使每个模块都能比较容易地进行编码。最终要精心实现的就是这写模块并以此构成完成完整的程序。这就是软件工程中的“自顶向下”的模块化设计模式
3)模块化设计模式的最大优点:使代码容易地被重复使用
4)模块化设计模式需要注意的问题:划分函数的标准是什么?注意程序的内聚性和耦合性。可能在程序中被重复调用的代码应该单独定义成一个模块。
把相关的语句组织在一起,并给他们注明相应的名称,利用这种方法把程序分块,这种形式的组合就是函数。
函数的使用通过函数调用机制实现。函数调用指定了被调用函数的名字和调用函数所需的信息(参数列表)
程序员编写完成制定人物的函数是用户自定义函数:标准库函数是C提供的可以在任何程序中的公共函数。
5)在一个完整的程序中,有且只有一个main()作为程序的入口点。其他函数都是直接或者间接地被main()调用
函数的定义和声明:
1)定义
return_type function_name(type var1,type var2,....,type VARN){/*函数体*/}
在C89中允许返回类型为int型的函数省略前面的int关键字,但C99和C++均不允许
注意,在现代的大型商业项目中,不允许省略返回类型为int型函数前面的int关键字
2)声明
声明一个函数: return_type function_name(type,type,...type);
必须以;结尾
3)main()不需要声明,它是程序执行的入口点
4)可变长参数列表
return_type function_name(type var1,...);
必须至少定义一个参数
int f1(...);这是违法的
原理:不管参数有多少,看成字符串,压栈,再逐一取出
例如printf()就是典型的例子
5)注意若函数无参数,声明时使用void关键字: int f1(void)
函数的调用:
1)两者方法向子程序传递变量:值调用和引用调用
值调用:把变量值复制到子程序的形参中。参数的修改对变量没有影响。
引用调用:把变量的地址复制到子程序的形参中,子程序通过地址访问实际变量。参数的修改能够影响用于子程序调用的变量的值
值调用例子一:
jellonwu :~/Desktop$ vim test9.c
#include <stdio.h>
int max(int,int);
int main()
{
int a = 1 , b = 2;
printf("the big one:%d\n",max(a,b));
}
int max(int a,int b)
{
return (a>b?a:b);
}
jellonwu :~/Desktop$ gcc test9.c -o test9
jellonwu :~/Desktop$ ./test9
the big one:2
值调用例子二:
jellonwu :~/Desktop$ vim test10.c
#include <stdio.h>
/*子函数声明*/
int square(int);
int cube(int);
void main()
{
int m = 12;
int n = 4;
printf("%d %d\n",square(m),m);
printf("%d %d\n",cube(n),n);
}
int square(int x)
{
x = x*x;
return x;
}
int cube(int y)
{
y = y*y*y;
return y;
}
jellonwu :~/Desktop$ gcc test10.c -o test10
jellonwu :~/Desktop$ ./test10
144 12
64 4
引用调用例子:
jellonwu :~/Desktop$ vim test11.c
#include <stdio.h>
void swap(int *x,int *y);
void main()
{
int i,j;
i = 12;
j = 36;
printf("i and j before swapping:%d %d\n",i,j);
swap(&i,&j); /*传递变量i和j的地址*/
printf("i and j after swapping:%d %d\n",i,j);
}
void swap(int *x,int *y)
{
int temp;
temp = *x; /*存储变量X的值*/
*x = *y; /*将y的值放入到x中*/
*y = temp; /*将x的值放入到y中*/
}
jellonwu :~/Desktop$ gcc test11.c -o test11
jellonwu :~/Desktop$ ./test11
i and j before swapping:12 36
i and j after swapping:36 12
递归方法:
必须在适当的位置防止条件判断语句用于强制放会。否则函数可能在被调用后永远也不返回。在开发时可用printf()和getchar()监视运行的推进并寻找错误
不要过分递归,会造堆栈溢出,程序崩溃
函数返回值:
1)在C89中,若非void型函数执行不含值的return语句,则返回无用值。这很糟糕。
2)编译时,函数基本分三类:
A.计算(纯函数):专门设计成对变量实施操作后返回一个基于操作的值
B.处理后返回操作的结果(成功或失败):如fopen().
C.无明显的返回值:这类函数是严格意义上的过程,没有返回值。应该定义成void型,可以防止误用
3)有时返回值的意义不大,如printf()返回写出的字节数