按着C风格编写C代码
2016-10-14 本文已影响110人
Sivin
标签(空格分隔): C语言
C语言源程序最小单位是函数
,本篇我们来讨论一下一个程序包含多个函数时所产生的几个问题。
1.局部变量
我们把声明在函数体内部的变量称为该函数的局部变量
(local variable)
int sum_digits(int n)
{
int sum = 0;//local variable
while(n>0){
sum +=n
n--;
}
return sum;
}
局部变量有以下性质:
- 自动存储期限:函数调用时内存空间自动分配,函数返回时回收分配,值无法保留。
- 块作用域:从变量声明点开始到所在函数体的末尾。
C99不要求函数一开始就进行变量声明,所有局部变量的作用域可能非常的小。
2.静态局部变量
在局部变量声明中放置单词static
修饰,可以使变量具有静态存储期限而不再是自动存储期限。因为静态存储的变量拥有永久的存储单元。所以整个程序执行期间都会保留变量的值。
作用域:静态局部变量的作用域,依然是块作用域。它对其他函数依然是不可见的,但是它会为将来同一个函数的再调用保留这些数据。
3.形式参数
形式参数和局部变量具有一样的性质。自动存储期限,块作用域,事实上,形式参数和局部变量的唯一区别是:在每次函数调用时对形式参数自动进行初始化。
4.外部变量(全局变量)
传递参数是给函数传递信息的一种方法。此外,函数还可以通过外部变量进行通信。外部变量是声明在函数体外部的变量。
外部变量(有时称为全局变量)的性质不同于局部变量:
- 静态存储期限:就如同声明为
static
的局部变量一样,外部变量拥有静态存储期限。存储在外部变量中的值将永久保留下来。- 文件作用域。外部变量拥有文件作用域:从变量声明点开始一直到所在文件的结尾,因此,跟随在外部变量声明之后的所有函数都可以访问(并修改)它。
案例:使用外部变量实现栈
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#define STACK_SIZE 100
int contents[STACK_SIZE];
int top = 0;
void make_empty(void) {
top = 0;
}
bool is_empty(void) {
return top == 0;
}
bool is_full(void) {
return top == STACK_SIZE ? true : false;
}
void stack_overflow(void) {
printf("数据压入失败,堆栈已满");
}
void stack_underflow(void) {
printf("数据出栈失败,堆栈以空");
}
void push(int i) {
if (is_full()) {
stack_overflow();
} else {
contents[top++] = i;
}
}
上面的例子:由于数组contents,和top在多个函数中都要调用。所以这里使用外部变量。
5.外部变量的利与弊
在多个函数必须共享一个变量或者少数函数共享大量的变量时,外部变量是很有用的。然而,在大多数情况下,对函数而言,通过形式参数进行通信比共享变量的方法更好,原因有一下几点:
- 在程序维护期间,如果改变外部变量(比如说改变它的数据类型)那么将要检查同一文件中的每一个函数,已确认该变化如何对函数产生影响。
- 如果外部变量被服了出错误的值,可能很难确定出错的函数。就好像处理大型聚会上的谋杀案时很难缩小嫌疑人的范围一样。
- 很难在其他程序中复用依赖于外部变量的函数,依赖外部变量的函数不是独立的,为了在另一个程序中使用该函数,必须带上次函数需要的外部变量。
5.程序块
c语言允许包含声明的符合语句
[程序块] {多条声明 多条语句}
构建c程序
到目前为止,我们已经知道一个c程序可以包含:
- 诸如#include 和#define这样的预处理指令
- 类型定义
- 外部变量声明
- 函数原型
- 函数定义
C语言对上述这些项的顺序要求极少,但是为了遵守这些规则,我们一般建议使用这样的方式来构建C程序:
- #include指令
- #define 指令
- 类型定义
- 外部变量声明
- 除main函数以外的其他函数的原型
- main函数定义
- 其他函数定义