8、外部变量和函数:作用域从声明处开始到文件的结尾处
9、外部变量的声明:声明变量的特性,尤其是变量的类型。
外部变量的定义:给变量设置存储空间。
如果int sp出现在函数的外部,这定义了外部变量sp,给sp设置了存储空间,同时作为剩下文件的声明;而extern int sp作为源文件余下部分的声明sp是int类型,但是并不创造变量或者保留内存空间。
10、在组成源程序的所有文件中,对外部变量的定义只能有一次,而其他文件可以通过extern声明来获取它。
11、外部变量的始化只能在定义中进行。
12、静态变量(static variables):对于进行了静态声明的外部变量,将它的作用域限制在了该文件的余下部分。其他文件的函数将不会获取到。静态变量的存储空间通过static被确定。
13、静态变量通常用来声明变量,但也会用来声明函数,函数一般来说都是全局有效的,但是通过static静态声明,函数的作用域会被限制在该文件中,其他文件的函数将不会引用到它。
14、函数的内部变量也可以被声明为静态变量,类似于自动变量,内部静态变量对于指定的函数也是局部有效的,但是和自动变量不同的是,它的值会一直保留,不像自动变量的值随着进入函数产生退出函数消失。所以内部静态变量给指定的函数提供一个私有的、永久的存储空间。
15、寄存器变量(register variables)声明:寄存器变量被放置在机器的寄存器中,这会导致程序运行地既小且快。寄存器变量的定义如下:register int x ,寄存器变量的声明只能用于自动变量和函数的形参上,如:
f(register unsigned m, register long n)
{
Register int I;
}
通常只会有很少一部分的变量可以被声明为寄存器变量,而且只有特定的类型被允许。获取寄存器变量的地址也是不可能的,在不同机器中对寄存器变量的限制也有所不同,所以对变量声明为寄存器变量时要格外小心。
16、在函数块中声明和初始化的自动变量在每次进入函数时都会再次初始化,而函数块中的静态变量只会在第一次进入该函数块的时候初始化。函数中的自动变量(包括函数形参)如果和函数外部的外部变量名字冲突时,函数内部的变量会覆盖外部的变量的作用域,这会导致隐含的混乱和错误,例如:
int x, y;
f(double x)
{
double y;
}
在函数内部时,x指的是double类型的x,y指的是double类型的y,外部变量x和y的作用域在函数内部被覆盖。
17、变量的初始化:对于外部变量和静态变量,如果初始化缺失,那么默认变量的值是0,对于自动变量和寄存器变量来说,如果没有初始化,那么变量的值没有明确定义,可能是随机的。对于外部变量和静态变量,初始化值必须是一个常量表达式,初始化只进行一次,通常发生在程序执行前。对于自动变量和寄存器变量来说,在每次进入函数的时候都要进行初始化。对于自动变量和寄存器变量,它的初始化值并不限定为一个常量,可以是先前定义的值,甚至是调用的函数。
18、初始化和赋值:初始化时变量赋值的一个简化。通常,我们并不在变量定义的时候初始化,而是在后来进行赋值,因为在较长的程序中,初始化会影响程序的阅读。
19、递归调用(recursion):递归调用并不会节省存储空间,也不会使程序运行的更快,但是却使程序更加紧凑,在写和读的方面也更加容易,特别是在像树状的数据结构定义方面非常方便。
20、The C Preprocessor待细读。