链接多个文件

原创
2016/10/20 21:46
阅读数 166

链接多个文件

在一个文件中可能需要引用另外一个文件中定义的全局变量或函数。

下面的例子是一个简单的数组操作程序,在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函数中使用:

#include <stdio.h>

extern int array[];   //导出全局变量的声明
extern int sum();     //导出函数的声明
extern int get_max();
extern void print();

int main(void)
{
  int all, max;
  all = sum();
  max = get_max();
  print();
  printf("the sum is %d, the max is %d\n", all, max);
  return 0;
}

运行结果如下:

array[1] : 2
array[2] : 7
array[3] : 6
array[4] : 4
array[5] : 8
the sum is 27, the max is 8

链接时符号解析规则 首先看两个概念:

  • 声明:表示告知编译器该变量的存在 如:int a;
  • 定义:不仅告知变量的存在,而且为该变量赋值,并分配内存空间 如:int a = 1;

当该变量的作用域内只有声明,而没有该变量的定义时,编译器会自动将第一个声明认为是 变量的定义,如下:

{
  //在这里声明变量b,由于在 该函数内找不到对变量b的定义
  //因此该声明被认为是变量的定义,这时分配了4个姊jie妹存储空间给b
  int b;
  b = 2;  //这是对变量b的赋值,不是定义
  return a + b;
}

C语言中的符号解析规则如下;

  1. 不允许有多个符号的定义,这里的符号指的是变量或者函数。
  2. 如果有一个符号定义和多个符号的声明,则选择被定义的符号。
  3. 如果有多个符号的声明,则从其中任选一个作为符号的定义。

链接规则的应用

实例1:

a.c中包含一个全局变量a的定义

#include <stdio.h>

int a = 123;  //一个全局变量

int main(void)
{
  return 0;
}

b.c中也包含一个全局变量的定义

int a = 321;  //同名的全局变量

void f(void)
{
  printf("function %f\n");
}

该例会造成链接错误,原因是两个文件中都对一个变量进行了定义,违反了第一条规则。

实例2

a.c中包含一个全局变量a的定义

#include <stdio.h>

void f(void); //函数的声明

int a = 123;  //全局变量的定义

int main(void)
{
  f();  //调用函数
  printf("a = %d\n", a);  //输出全局变量
  return 0;
}

b.c中包含一个全局变量a的声明:

int a;  //全局变量的声明

void f()
{
  a = 121;  //对全局变量赋值
}

由于两个源文件中出现了对变量a的定义和声明,因此其符号解析符合第二条规则,所以全 局变量a在f()中被修改为121. 输出为:a = 121

实例3

a.c中包含全局变量a定义

#include <stdio.h>

void f(void); //函数的声明

int a = 123;  //全局变量的定义
int b = 321;

int main(void)
{
  f();  //调用函数
  printf("a = %d, b = %d\n", a, b);  //输出变量a和b
  return 0;
}

b.c中包含对全局变量a的声明

double a;  //全局变量的声明

void f()
{
  a = 0.0;  //对变量a赋值
}

运行结果为: a = 0, b = 0

这是为什么(⊙o⊙)? 两个源文件分别包含全局变量a的定义和全局变量a的声明,根据第二条规则,不会出现链接错误,编译器会选择符号的定义。这时b.c中函数f()内对变量a的操作实际上操作的是a.c中的全局变量a。所不同的是由于在b.c总声明的变量为双精度型,所以对该变量进行赋值为0.0时,需要将由a所指向的内存空间的首地址开始的8个字节清0,而不是4个。这个时候,变量a后面的变量b的存储空间也被覆盖了。因此输出的a和b的值都是0.

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部