連結規則引發的全域性變數的值被改變
阿新 • • 發佈:2019-02-05
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