1. 程式人生 > >連結規則引發的全域性變數的值被改變

連結規則引發的全域性變數的值被改變

C語言中符號解析規則如下:

1.不允許有多個符號的定義,這裡的符號指的是變數或者函式

2.如果有一個符號定義和多個符號的宣告,則選擇被定義的符號。

3.如果有多個符號的宣告,則從其中任選一個作為符號的定義。

宣告和定義有什麼區別:

宣告表示告知編譯器,該變數的存在,此時是為該變數分配儲存空間的。

定義,不僅告知編譯器該變數存在,而且為該變數賦值。由於需要賦值,所以該變數的儲存空間就被分配了。

當該變數的作用域範圍內只有宣告,而沒有該變數的定義時,編譯器會自動的將第一個宣告認為是變數的定義。

void f(){

   int b;  /*在這裡宣告變數b,由於在該函式中,沒有找到對變數b的定義。

        因此該宣告被認為是變數的定義,這時分配了4個位元組儲存空間給b

         */

   b = 2;   //這裡是對變數進行賦值,不是定義。

}

下面這個問題,我總結為連結規則所引發的全域性變數值被覆蓋的情形:

a.c 函式如下:

//下面是a.c檔案中的程式碼

#include
void f(void);

//全域性變數的定義
int a = 123;
int b = 121;

int main(void)
{
    f();
    printf("a = %d,b = %d\n",a,b);
    return 0;
}

//下面是b.c中的程式碼

double a;
void f()
{ 
    a = 0.0;
}
最後的輸出結果會是多少?先來分析一下!

兩個原始檔中都有對全域性變數a的定義和全域性變數a的宣告,根據如上規則2,所以不會造成連結錯誤。編譯器會選擇符號的定義。這是f()函式執行的時候,裡面呼叫的 a 其實是在a.c中定義的全域性變數。所不同的是由於b.c中宣告的變數型別為雙精度型,所以對該變數進行賦值為0.0的時候,需要將由 a 所指的記憶體空間的首地址開始的8個位元組清 0 ,而不是4個位元組。因此變數 a 後面的變數b的儲存空間就被覆蓋掉了。因此,最後輸出的結果是:a = 0, b = 0