程序结构
1. 局部变量
我们在把函数体内声明的变量称为该函数的局部变量。
-
自动存储期:变量的存储期是程序执行时,能够确保变量的存储空间必定存在的那一部分时间。通常来说,局部变量的存储空间是在包含该变量的函数被调用时“自动”分配的,函数返回时收回分配,所以称这种变量具有自动存储期。包含局部变量的函数返回时,局部变量的值无法保留。当再次调用该函数时,无法保证变量仍拥有原先的值。
-
块作用域:变量的作用域时可以引用该变量的那一部分程序文本。局部变量拥有块作用域:从变量声明的点开始一直到所在函数体的末尾。因为局部变量的作用域不能延伸到其所属函数之外,所以这也是其他函数可以把同名变量用于别的用途。
1.1 静态局部变量
在局部变量声明中放置单词static可以使变量具有静态存储期而不再是自动存储器。因为具有静态存储期的变量拥有永久的存储单元,所以在整个程序执行期间都会保留变量的值。
- 静态局部变量始终有块作用域,所以它对其他函数是不可见的。概括来说,静态变量是对其他函数隐藏数据的地方,但是它会为将来同一个函数的再调用保留这些数据。
2. 形式参数
形式参数拥有和局部变量一样的性质,即自动存储期和块作用域。事实上,形式参数和局部变量唯一真正的区别是,在每次函数调用时对形式参数自动进行初始化(调用中通过赋值获得相应的实际参数的值);
3. 外部变量(全局变量)
传递参数是给函数传送信息的一种方法。函数还可以通过外部变量进行通信。外部变量是声明在任何函数体外的。
-
静态存储期:就如同声明为static的局部变量一样,外部变量拥有静态存储区。存储在外部变量中的值将永久保存下来。
-
文件作用域:外部变量拥有文件作用域:从变量被声明的点开始一直到所在文件的末尾。因此,跟随在外部变量声明之后的所有函数都可以访问(并修改)它。
3.1 外部变量的利与弊
在许多函数必须共享一个变量时或者少数几个函数共享大量变量时,外部变量是很有用的。然而在大多数情况下,对函数而言,通过形式参数进行通信比共享变量的方法更好,原因列举如下:
-
在程序维护期间,如果改变外部变量,那么将需要检查同一文件中的每个函数,以确认该变化如何对函数产生影响。
-
如果外部变量被赋了错误的值,可能很难找到出错的函数,就好像侦察大型聚会上的谋杀案很难缩小嫌疑人范围一样。
-
很难在其他程序中复用依赖外部变量的函数。依赖外部变量的函数不是“独立的”。为了在另外一个程序中使用该函数,必须带上此函数需要的外部变量。
4. 程序块
示例:
if(i > j){
int temp = i;
i = j;
j = temp;
}
-
这里整个if语句是一个程序块;if语句的每个子句也是程序块。默认情况下,声明在程序块中的变量的存储期是自动的:进入程序块时为变量分配存储单元,退出程序块时收回分配的空间。变量具有块作用域,就是说,不能在程序块外引用。
-
函数体是程序块。在需要临时使用变量时,函数体内的程序块也是非常有用的,在上面这个例子中,我们需要一个临时变量以便可以交换i和j的值。在程序块中放置临时变量有两个好处:
-
避免函数体起始位置的声明与只是临时使用的变量相混淆
-
减少了名字冲突。在此例中,名字temp可以根据不同的目的用于同一函数中的其他地方,在程序块中声明的变量temp严格属于局部程序块。
-
C99允许在程序块的任何地方声明变量,就像允许在函数体内的任何地方声明变量一样。
-
5. 构建C程序
单个文件的程序的创建
-
include和#define这样的预处理指令
- 类型定义
- 外部变量声明
- 函数原型
- 函数定义
C语言对上述这些项的顺序要求极少:执行到预处理指令所在的代码行时,预处理指令才会起作用;类型名定义后才可以使用;变量声明后才可以使用。虽然C语言对函数没有什么要求,但是在这里强烈建议在第一次调用函数前要对每个函数进行定义或声明。
下面是一种编排的顺序的例子:
-
include指令;
-
define指令
- 类型定义
- 外部变量的声明
- 除main函数之外的函数的原型
- main函数的定义
- 其他函数的定义
- 因为#include指令带来的信息可能在程序中的好几个地方都需要,所以先放置这条指令时合理的。#define指令创建宏,对这些宏的使用通常遍布整个程序。类型定义放置在外部变量声明的上面是合乎逻辑的,因为这些外部变量的声明可能会引起刚刚定义的类型。接下来,声明外部变量使得它们对于跟随在其后的所有函数都是可用的。在编译器看见原型之前调用函数,可能会产生问题,而此时声明除了main函数以外的所有的函数都可以避免这些问题。这种方法也使得无论用什么顺序编排函数定义都是有可能的。例如,根据函数名的字母顺序编排,或者把相关函数组合在一起编排。在其他函数前定义main函数使得阅读程序的人很容易定位程序的起始点。
- 最后的建议:在每个函数定义之前放盒型注释可以给出函数名、描述函数的目的、讨论每个形式参数的含义、描述返回值并罗列所有的副作用。
0 条评论