下邊的代碼分別是什麼含義?
int a;
int a=0;
static int a;
static int a = 0;
extern int a;
extern int a = 0;//ERROR
1.變量聲明和定義的區別?
變量可以有多次聲明,但只能有一次定義。
聲明只是說我有這個變量,也有可能這個變量不是在我這個文件中開辟的內存空間,所以聲明可以有多次。定義只能有一次,如果一個變量有多次定義,則鏈接時就會困惑不知道是該鏈接哪一個,訪問變量時也不能確定訪問的是哪個。
將C語言梳理一下,分布在以下10個章節中:
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 5int
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