10.1 局部变量
局部:在函数体内声明的变量称为相对于函数的局部。
存储期限(storage duration):调用闭合函数时“自动”分配局部变量的存储单元,函数返回时收回分配。
特点:
- 自动存储期限:调用闭合函数时“自动”分配局部变量的存储单元,函数返回时收回分配。在闭合函数返回时收回分配。
- 程序快作用域:变量的作用域是可以参考变量的程序文本的部分。从变量声明的点开始一直到闭合函数的末尾。局部变量拥有程序块作用域。
1 | int log2(int n){ |
10.1.1 静态存储期限:static
特点:具有静态存储期限的变量拥有永久的存储单元,所以会在整个程序执行期间会保留变量的值。
- 静态局部变量始终有程序块作用域,它对其他函数而言是不可见的
- 静态变量是隐藏来自其他函数的数据的地方,但是它会为将来同一个函数的调用保留这些数据。
声明方式:在局部变量声明中放置单词static
可以使用变量从自动存储期限变为静态存储期限。
1 | void f(void){ |
10.1.2 形式参数
和局部变量比较
- 相同点:自动存储期限、块级作用域
- 不同点:在每次函数调用时对形式参数自动进行初始化(调用中通过赋值获得实际参数的值)
10.2 外部变量
又名:全局变量
声明位置:外部变量是声明在任何函数体外的。
性质:
- 静态存储期限:同声明的static的局部变量一样,外部变量拥有静态存储期限。存储在外部变量中的值将永久保留下来。
- 文件作用域:从变量声明的点开始一直到闭合文件的末尾。跟随在外部变量声明后的所有函数都可以访问它。
10.2.1 程序:用外部变量实现栈
栈(stack):像数组一样,栈可以存储具有相同数据类型的多个数据项。
操作方式:LIFO(后进先出),占中数据项的操作是十分受限制的,可以忘栈中压入数据,或者从栈中弹出数据项。禁止测试或修改不在栈顶的数据项。
c语言实现:把元素存储在数组中,称为constents
,命名为top的一个整型变量用来标记栈栈顶的位置。栈为空时,top值为0。为了往栈中压入数据项,可以把数据项简单存储在contents中标记为top的位置上,然后自增top。弹出数据项则要求自减top,然后用它作为contents
中标记为top的位置上,谈后自增top。弹出数据项则要求自减top,然后用它作为contents
的索引取回弹出的数据项。
1 |
|
10.2.2 外部变量的利与弊
利:有利于多个函数必须共享一个变量或者上述几个函数共享大量变量。
蔽:
- 可维护性差:如果改变外部变量,那么需要检查同一个文件中的每个函数,确认该改变对函数的影响。
- 可读性差:如果外部变量出现问题,难以确定导致这个值发生错误的函数。
- 可复用性差:很难再其他城程序中复用依赖于外部变量的函数。因为以来外部变量的函数不是“独立的”。
技巧:为了提高可阅读性和可能的错误,使用外部变量时,确保它们都拥有有意义的名字。
10.2.3 程序:猜数(略)
10.3 程序块
语法:
1 | { |
作用域:程序块中的变量具有进入程序块时为存储变量分配单元,而在退出程序块时解除分配。
函数体(也是程序块)放置临时变量的优点:
- 避免函数体起始位置的声明与只是临时使用的变量相混淆
- 减少了名字冲突
1 | if(i > j){ |
10.4 作用域
规则:
- 标识符拥有文件作用域,即在所声明的闭合程序块内有效
- 新的声明临时会“隐藏”旧的声明
- 在程序块结束后后面,被“隐藏”的标识符重新获得旧的含义
1 | /*第1个*/ |
10.5 构建c 程序
程序构成要素:
- 预处理指令:诸如
#include
和#define
- 类型定义
- 函数声明和外部变量声明
- 函数定义
建议编排顺序:
- #include指令
- define指令
- 类型定义(typedef)
- 外部变量声明
- 除main函数之外的函数原型
- main函数的定义
- 其他函数的定义
建议函数注释:盒形注释
- 函数名
- 描述函数的目的
- 讨论每个参数的含义
- 描述返回值
- 罗列任何的副作用