一个工程由许多的文件组成,当工程中的多个文件编译结束后就需要由链接器将这些模块链接起来成为一个整体的可执行程序。但是,在这个链接过程中,如果出现一些状况的时候就不能将这些模块链接成一个程序。接下来,研究一下这个链接的过程!
★链接多个文件
为了使程序的模块化更强,代码更易于管理,可以将同类型的代码存储在一个文件中。这时,每个文件代表着一类函数的代码,这些代码使用同样的资源,完成同样的操作。这与Java中的类、对象、方法想、很类似。在一个文件中,很可能需要引用另一文件中定义的全局变量或者函数,因此会导致多个C语言文件的链接问题。
例子:
一个简单的数组操作程序,这个程序计算数组中所有元素的和,可以得到数组中最大的元素,可以遍历输出数组。这些操作均实现为函数,而这些函数由于都操作目标数组,因此属于同一类型的操作。
operate.c
#include <stdio.h>
#define MAX 5
int array[MAX] = {2,7,6,4,8};
/**计算数组中所有元素的和**/
int sum()
{
int i;
int n;
n = 0;
for(i = 0; i < MAX; i++)
{
n += array[i];
}
return n;
}
/**得到数组中最大的元素**/
int get_max()
{
int max;
int i;
i = 0;
max = array[i];
for(i = 0;i < MAX; i++)
if(array[i] > max)
max = array[i];
return max;
}
/**输出数组中每个元素的值**/
void print()
{
int i;
for(i = 0; i < MAX; i ++)
{
printf("array[%d]:%d\n",i + 1,array[i]);
}
}
main.c
#include <stdio.h>
extern int array[];
extern int sum();
extern int get_max();
extern void print();
int main()
{
int all,max;
all = sum();
max = get_max();
print();
printf("the sum:%d,the max:%d\n",all,max);
return 0;
}
★链接时符号解析规则
声明:是告诉编译器该变量存在,此时是不为该变量分配存储空间的。
定义:不仅告诉编译器该变量存在,而且为该变量赋值,也就为该变量分配了内存空间了。
注:当该变量的作用域范围内只有声明,而没有该变量的定义时,编译器会自动将第一个声明认为是变量的定义。
C语言的符号解析规则:
●不允许有多个符号的定义,符号代表的是变量或者函数
●如果有一个符号的定义和多个符号的声明,则选择被定义的符号
●如果有多个符号的声明,则从其中任选一个作为符号的定义。
★连接规则的应用
实例1、在一个工程中定义了两个函数或者两个全局变量
实例2、一个文件中包含一个全局变量a的定义,另一个文件是全局变量的声明
#include <stdio.h>
void f(void)
int a = 123;//全局变量的定义
int main()
{
f();
printf("a = %d\n",a);
return 0;
}
int a;//全局变量的声明
void f()
{
a = 121;
}
两个源文件中分别出现了对全局变量a的定义和声明,并且符合解析规则的第二条:如果有一个符号的定义和多个符号的声明,则选择被定义的符号。所以全局变量a被f()函数修饰为121,被保存到全局变量a的存储空间 中。
实例3、源文件中只有变量的声明
#include <stdio.h>
void f(void)
int a;//全局变量的声明
int main()
{
a = 123;
f();
printf("a = %d\n",a);
return 0;
}
int a;//全局变量的声明
void f()
{
a = 121;
}
当两个文件中都含有对全局变量的声明时,根据规则3,编译器会选择最先扫描到的那个声明作为变量的定义。