不积硅步无以至千里
分类: C/C++
2012-01-02 16:25:46
一个C语言程序可以由多个分别编译的部分组成,这些不同部分通常通过一个叫做连接器(也叫连接编译,或者载入器)的程序合并成一个整体。
4.1 什么是连接器
C语言的一个重要思想就是分别编译(separate complining),即若干个源程序可以在不同的时候分别编译,然后在恰当的时候整合在一起。连接器一般是与C语言分开的,它并不了解C语言的细节。尽管连接器并不了解C语言的细节,但是它却能够理解机器语言和内存布局。
典型的编译器把由编译器汇编生成的若干个目标模块整合成一个称为载入模块或者可执行文件的实体,该实体能够被操作系统直接执行。连接器通常把目标模块看成是由一组类外部对象(extern objects)组成的。
连接器的一个重要作用就是处理命名冲突。
4.2 声明与定义
下面的声明语句:
如果该语句出现在所有函数之外,那么它就被称为外部对象的定义。这个定义说明了a是一个外部整型变量,同时为a分配了内存空间。
下面的语句:
并不是一个定义语句。这个语句依然说明了a是一个整型变量,但是因为它包含了extern关键字,这就显式地说明了a的存储空间是在其他地方分配的。从连接器的角度看,上述语句只是一个对a的引用,而不是定义。即使它出现在一个函数的内部,也具有同样的含义。
每个外部对象都必须在程序的某个地方定义。
如果一个程序中包含
则这个程序就必须在别的地方包含
这两个语句可以在同一个源文件中,也可以出现在不同的源文件中。
4.3 命名冲突与static修饰
两个具有相同名称的外部对象实际上代表的是同一个对象。
以下声明语句
其含义与以下语句相同
只不过,a的作用域被限定在一个源文件中,对于其他源文件,a是不可见的。因此,如果若干个函数需要共享同一组外部对象,可以将这些函数放到同一个源文件中,把它们需要使用的外部对象也都在同一个文件中用static修饰。
static修饰符不仅适用于变量,也适用于函数。
如果函数f需要调用函数g,而且只有f可以调用g,我们可以把f和g放到同一个文件中,并且声明g为static:
我们可以在多个源文件中定义同名的函数g,只要所有的函数g都被定义为static,或者仅仅只有一个函数不是static。
4.4 形参、实参与返回值
任何一个C函数都有返回值,要么是void,要么是函数生成结果的类型。
如果一个函数在定义或声明之前被调用,那么它的返回类型就默认为整型。
4.5 检查外部类型
与
尽管在某些上下文环境中,数组与指针非常相似,但它们毕竟是不同的。
因此,有如下改法:
或者
C语言的规则是:如果一个未声明的标识符后面跟一个开括号,那么它将被视为一个返回整型的函数。
4.6 头文件
每个外部对象只在一个地方声明,这个声明的地方一般在一个头文件中,需要用到该外部对象的所有模块都应该包含这个头文件。特别需要指出的是定义该外部对象的模块也应该包含这个文件。