連接多個文件

連接多個文件

在一個文件中可能須要引用另一個文件中定義的全局變量或函數。數組

下面的例子是一個簡單的數組操做程序,在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函數中使用:code

#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;

當該變量的做用域內只有聲明,而沒有該變量的定義時,編譯器會自動將第一個聲明認爲是 變量的定義,以下:get

{
  //在這裏聲明變量b,因爲在 該函數內找不到對變量b的定義
  //所以該聲明被認爲是變量的定義,這時分配了4個姊jie妹存儲空間給b
  int b;
  b = 2;  //這是對變量b的賦值,不是定義
  return a + b;
}

C語言中的符號解析規則以下;編譯器

  1. 不容許有多個符號的定義,這裏的符號指的是變量或者函數。
  2. 若是有一個符號定義和多個符號的聲明,則選擇被定義的符號。
  3. 若是有多個符號的聲明,則從其中任選一個做爲符號的定義。

連接規則的應用

實例1:

a.c中包含一個全局變量a的定義io

#include <stdio.h>

int a = 123;  //一個全局變量

int main(void)
{
  return 0;
}

b.c中也包含一個全局變量的定義編譯

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

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

該例會形成連接錯誤,緣由是兩個文件中都對一個變量進行了定義,違反了第一條規則。function

實例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.

相關文章
相關標籤/搜索