歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

C語言全局變量extern、static的含義

下邊的代碼分別是什麼含義?

int a;

int a=0;

static int a;

static int a = 0;

extern int a;

extern int a = 0;//ERROR

1.變量聲明和定義的區別?

變量可以有多次聲明,但只能有一次定義。

聲明只是說我有這個變量,也有可能這個變量不是在我這個文件中開辟的內存空間,所以聲明可以有多次。定義只能有一次,如果一個變量有多次定義,則鏈接時就會困惑不知道是該鏈接哪一個,訪問變量時也不能確定訪問的是哪個。

將C語言梳理一下,分布在以下10個章節中:

  1. Linux-C成長之路(一):Linux下C編程概要 http://www.linuxidc.com/Linux/2014-05/101242.htm
  2. Linux-C成長之路(二):基本數據類型 http://www.linuxidc.com/Linux/2014-05/101242p2.htm
  3. Linux-C成長之路(三):基本IO函數操作 http://www.linuxidc.com/Linux/2014-05/101242p3.htm
  4. Linux-C成長之路(四):運算符 http://www.linuxidc.com/Linux/2014-05/101242p4.htm
  5. Linux-C成長之路(五):控制流 http://www.linuxidc.com/Linux/2014-05/101242p5.htm
  6. Linux-C成長之路(六):函數要義 http://www.linuxidc.com/Linux/2014-05/101242p6.htm
  7. Linux-C成長之路(七):數組與指針 http://www.linuxidc.com/Linux/2014-05/101242p7.htm
  8. Linux-C成長之路(八):存儲類,動態內存 http://www.linuxidc.com/Linux/2014-05/101242p8.htm
  9. Linux-C成長之路(九):復合數據類型 http://www.linuxidc.com/Linux/2014-05/101242p9.htm
  10. Linux-C成長之路(十):其他高級議題

C++ Primer Plus 第6版 中文版 清晰有書簽PDF+源代碼 http://www.linuxidc.com/Linux/2014-05/101227.htm

C++11中正則表達式測試 http://www.linuxidc.com/Linux/2012-08/69086.htm

int a;是聲明還是定義?

********************************************

1 2 3 4 5 int a; int main() { a = 0; //在這裡,可以給變量a賦值,說說明上方int a 是定義。 }

********************************************

如果此時我們單純的認為int a;就是定義了一個變量,那麼我們在int a;下再加一句int a;如下:

int a;

int a;

int main()

{

a = 0;

}

編譯是否通過?結果會讓我們大吃一驚。

如果按照上述結論int a是定義的話,現在就應該會報重定義的錯了,可是編譯器並沒有報錯,為什麼呢?

這就說明:不能簡單憑借有沒有賦初值來判斷變量是聲明還是定義。賦了值的一定是定義,沒有賦值的可以是聲明也可以是定義,要根據語境來判斷。

例子中int a;可能是聲明也可能是定義。如果代碼中出現多次int a;編譯器則會把其中一個當成定義,其他都會看成聲明。也就是說像int a;這樣沒有給它賦初值的語句可以是聲明也可以是定義。

 

******************************************

int a=1;

int a;

int main()

{

a = 0;

}

沒有錯,第一句是定義,第二句是聲明

******************************************

但是像下邊這樣

int a=1; //給a開辟了一塊內存

int a=1; //給a開辟了一塊內存

int main()

{

a = 0;

}

就會報重定義的錯了。因為這相當於每條語句都為a開辟了一塊內存,在鏈接的時候就不知道a到底是那塊內存了

******************************************

 

在單個c源文件中很清楚,關於變量的錯誤主要是在多個相互聯系的源文件中。

====a.h============

int a;

===================

***b.c*************

#include"a.h"

 

int main()

{

a = 0;

}

********************

***c.c**************

#include"a.h"

 

int main()

{

a = 0;

}

******************

這個時候在b.c中 c.c中都有一個int a; 編譯程序gcc b.c c.c 沒問題,因為這個時候其中一個是定義,另一個是聲明。

2.extern的含義?

上面的例子如果將a.h中 int a;改為 int a = 0;則編譯器就會報a被多次定義的錯了。對應上邊所說的賦了值的一定是定義。沒賦值的可以是聲明也可以定義。

int a比較明顯。有的可能會在頭文件中寫成const char* item[]={"aa","bb"};這時編譯也會報錯。這和int a=0;沒有區別。所以在頭文件中我們應該避免給變量賦初值。

頭文件裡只對變量進行聲明這個時候就應該加上extern關鍵字 extern int a;

這個時候就表示 這個a只在這個頭文件中聲明,而不是在這裡定義的,是在某一個cpp文件中定義,開辟內存的。extern關鍵字就代表只是聲明一個變量,所以文章開頭 extern int a=0;是錯誤的 因為只是聲明並沒有為它開辟空間是不可以賦值的。

這個時候就可以在c.c裡 int a=10;為a定義。 在b.c裡就可以訪問a了。代碼如下:

====a.h============

extern int a;

===================

****c.c************

include "a.h"

int a = 10;

*******************

 

****b.c***********

include "a.h"

 

void main()

{

printf("%d",a); //這個時候多個文件include頭文件a.h就可以正常訪問變量a了,a實際是在c.c裡賦的值

}

********************

3.static 是什麼含義?

翻譯過來就是靜態的意思。還是原來的例子。

====a.h============

extern int a;

===================

****c.c************

include "a.h"

staitc int a = 10;

void main()

{

printf("the a in c.c is %d",a);

}

*******************

 

****b.c***********

include "a.h"

staitc int a = 100;

void main()

{

printf("the a in b.c is %d",a);

}

*************************

這個時候沒有報錯。static關鍵字表示 這個a只在自身范圍內有效。和外邊沒有關系。不會和外邊去鏈接,所以沒有沖突,b.c和a.c裡的a不是同一塊內存 是各自的內存。

extern 函數也是一樣。

====a.h============

extern int add(int var1);

===================

****c.c************

include "a.h"

staitc int a = 10;

int add(int var1)

{

a+=var1;

}

*******************

 

****b.c***********

include "a.h"

staitc int a = 100;

void main()

{

add(15);

printf("the a in b.c is %d",a); //結果仍是100

}

*************************

說明 extern的方法改變的a是方法被定義的文件(c.c)裡的變量a

Copyright © Linux教程網 All Rights Reserved